Version 1.0.2 mit node_modules Verzeichnis

This commit is contained in:
ISA
2024-10-02 07:58:24 +02:00
parent f353a06b1b
commit 62b6e55a0a
68228 changed files with 4548477 additions and 651 deletions

25
node_modules/cypress/README.md generated vendored Normal file
View File

@@ -0,0 +1,25 @@
# Cypress
Fast, easy and reliable testing for anything that runs in a browser.
## What is this?
[Cypress](https://www.cypress.io/) comes packaged as an `npm` module, which is all you need to get started testing.
After installing you'll be able to:
- Open Cypress from the CLI
- Run Cypress from the CLI
- `require` Cypress as a module
## Install
Please check our [system requirements](https://on.cypress.io/installing-cypress).
```sh
npm install --save-dev cypress
```
## Documentation
Please [visit our documentation](https://on.cypress.io/cli) for a full list of commands and examples.

11
node_modules/cypress/angular-signals/README.md generated vendored Normal file
View File

@@ -0,0 +1,11 @@
# @cypress/angular-signals
Mount Angular components in the open source [Cypress.io](https://www.cypress.io/) test runner. This package is an extension of `@cypress/angular`, but with [signals](https://angular.dev/guide/signals) support.
> **Note:** This package is bundled with the `cypress` package and should not need to be installed separately. See the [Angular Component Testing Docs](https://docs.cypress.io/guides/component-testing/angular/overview) for mounting Angular components. Installing and importing `mount` from `@cypress/angular-signals` should only be done for advanced use-cases.
## Development
Run `yarn build` to compile and sync packages to the `cypress` cli package.
## [Changelog](./CHANGELOG.md)

View File

@@ -0,0 +1,11 @@
# @cypress/angular-signals
Mount Angular components in the open source [Cypress.io](https://www.cypress.io/) test runner. This package is an extension of `@cypress/angular`, but with [signals](https://angular.dev/guide/signals) support.
> **Note:** This package is bundled with the `cypress` package and should not need to be installed separately. See the [Angular Component Testing Docs](https://docs.cypress.io/guides/component-testing/angular/overview) for mounting Angular components. Installing and importing `mount` from `@cypress/angular-signals` should only be done for advanced use-cases.
## Development
Run `yarn build` to compile and sync packages to the `cypress` cli package.
## [Changelog](./CHANGELOG.md)

View File

@@ -0,0 +1,136 @@
/// <reference types="cypress" />
import { InputSignal, WritableSignal, Type } from '@angular/core';
import { TestModuleMetadata, ComponentFixture, TestComponentRenderer } from '@angular/core/testing';
/**
* Additional module configurations needed while mounting the component, like
* providers, declarations, imports and even component @Inputs()
*
* @interface MountConfig
* @see https://angular.io/api/core/testing/TestModuleMetadata
*/
interface MountConfig<T> extends TestModuleMetadata {
/**
* @memberof MountConfig
* @description flag to automatically create a cy.spy() for every component @Output() property
* @example
* export class ButtonComponent {
* @Output clicked = new EventEmitter()
* }
*
* cy.mount(ButtonComponent, { autoSpyOutputs: true })
* cy.get('@clickedSpy).should('have.been.called')
*/
autoSpyOutputs?: boolean;
/**
* @memberof MountConfig
* @description flag defaulted to true to automatically detect changes in your components
*/
autoDetectChanges?: boolean;
/**
* @memberof MountConfig
* @example
* import { ButtonComponent } from 'button/button.component'
* it('renders a button with Save text', () => {
* cy.mount(ButtonComponent, { componentProperties: { text: 'Save' }})
* cy.get('button').contains('Save')
* })
*
* it('renders a button with a cy.spy() replacing EventEmitter', () => {
* cy.mount(ButtonComponent, {
* componentProperties: {
* clicked: cy.spy().as('mySpy)
* }
* })
* cy.get('button').click()
* cy.get('@mySpy').should('have.been.called')
* })
*/
componentProperties?: Partial<{
[P in keyof T]: T[P] extends InputSignal<infer V> ? InputSignal<V> | WritableSignal<V> | V : T[P];
}>;
}
/**
* Type that the `mount` function returns
* @type MountResponse<T>
*/
type MountResponse<T> = {
/**
* Fixture for debugging and testing a component.
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture
*/
fixture: ComponentFixture<T>;
/**
* The instance of the root component class
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture#componentInstance
*/
component: T;
};
declare class CypressTestComponentRenderer extends TestComponentRenderer {
insertRootElement(rootElId: string): void;
removeAllRootElements(): void;
}
/**
* Mounts an Angular component inside Cypress browser
*
* @param component Angular component being mounted or its template
* @param config configuration used to configure the TestBed
* @example
* import { mount } from '@cypress/angular-signals'
* import { StepperComponent } from './stepper.component'
* import { MyService } from 'services/my.service'
* import { SharedModule } from 'shared/shared.module';
* it('mounts', () => {
* mount(StepperComponent, {
* providers: [MyService],
* imports: [SharedModule]
* })
* cy.get('[data-cy=increment]').click()
* cy.get('[data-cy=counter]').should('have.text', '1')
* })
*
* // or
*
* it('mounts with template', () => {
* mount('<app-stepper></app-stepper>', {
* declarations: [StepperComponent],
* })
* })
*
* @see {@link https://on.cypress.io/mounting-angular} for more details.
*
* @returns A component and component fixture
*/
declare function mount<T>(component: Type<T> | string, config?: MountConfig<T>): Cypress.Chainable<MountResponse<T>>;
/**
* Creates a new Event Emitter and then spies on it's `emit` method
*
* @param {string} alias name you want to use for your cy.spy() alias
* @returns EventEmitter<T>
* @example
* import { StepperComponent } from './stepper.component'
* import { mount, createOutputSpy } from '@cypress/angular-signals'
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { change: createOutputSpy('changeSpy') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@changeSpy').should('have.been.called')
* })
*
* // Or for use with Angular Signals following the output nomenclature.
* // see https://v17.angular.io/guide/model-inputs#differences-between-model-and-input/
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { count: signal(0), countChange: createOutputSpy('countChange') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@countChange').should('have.been.called')
* })
*/
declare const createOutputSpy: <T>(alias: string) => any;
export { CypressTestComponentRenderer, MountConfig, MountResponse, createOutputSpy, mount };

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,74 @@
{
"name": "@cypress/angular-signals",
"version": "0.0.0-development",
"description": "Test Angular Components using Signals with Cypress",
"main": "dist/index.js",
"scripts": {
"prebuild": "rimraf dist",
"build": "rollup -c rollup.config.mjs",
"postbuild": "node ../../scripts/sync-exported-npm-with-cli.js",
"check-ts": "tsc --noEmit",
"dev": "rollup -c rollup.config.mjs -w",
"lint": "eslint --ext .js,.ts,.json, ."
},
"dependencies": {},
"devDependencies": {
"@angular/common": "^17.2.0",
"@angular/core": "^17.2.0",
"@angular/platform-browser-dynamic": "^17.2.0",
"@cypress/mount-utils": "0.0.0-development",
"typescript": "~5.4.5",
"zone.js": "~0.14.6"
},
"peerDependencies": {
"@angular/common": ">=17.2",
"@angular/core": ">=17.2",
"@angular/platform-browser-dynamic": ">=17.2",
"rxjs": ">=7.5.0",
"zone.js": ">=0.13.0"
},
"files": [
"dist"
],
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/blob/develop/npm/angular-signals/#readme",
"bugs": "https://github.com/cypress-io/cypress/issues/new?assignees=&labels=npm%3A%20%40cypress%2Fangular&template=1-bug-report.md&title=",
"keywords": [
"angular",
"cypress",
"cypress-io",
"test",
"testing"
],
"contributors": [
{
"name": "Bill Glesias",
"social": "@atofstryker"
}
],
"module": "dist/index.js",
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"outputs": [
"{workspaceRoot}/cli/angular-signals"
]
}
}
},
"standard": {
"globals": [
"Cypress",
"cy",
"expect"
]
}
}

136
node_modules/cypress/angular-signals/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,136 @@
/// <reference types="cypress" />
import { InputSignal, WritableSignal, Type } from '@angular/core';
import { TestModuleMetadata, ComponentFixture, TestComponentRenderer } from '@angular/core/testing';
/**
* Additional module configurations needed while mounting the component, like
* providers, declarations, imports and even component @Inputs()
*
* @interface MountConfig
* @see https://angular.io/api/core/testing/TestModuleMetadata
*/
interface MountConfig<T> extends TestModuleMetadata {
/**
* @memberof MountConfig
* @description flag to automatically create a cy.spy() for every component @Output() property
* @example
* export class ButtonComponent {
* @Output clicked = new EventEmitter()
* }
*
* cy.mount(ButtonComponent, { autoSpyOutputs: true })
* cy.get('@clickedSpy).should('have.been.called')
*/
autoSpyOutputs?: boolean;
/**
* @memberof MountConfig
* @description flag defaulted to true to automatically detect changes in your components
*/
autoDetectChanges?: boolean;
/**
* @memberof MountConfig
* @example
* import { ButtonComponent } from 'button/button.component'
* it('renders a button with Save text', () => {
* cy.mount(ButtonComponent, { componentProperties: { text: 'Save' }})
* cy.get('button').contains('Save')
* })
*
* it('renders a button with a cy.spy() replacing EventEmitter', () => {
* cy.mount(ButtonComponent, {
* componentProperties: {
* clicked: cy.spy().as('mySpy)
* }
* })
* cy.get('button').click()
* cy.get('@mySpy').should('have.been.called')
* })
*/
componentProperties?: Partial<{
[P in keyof T]: T[P] extends InputSignal<infer V> ? InputSignal<V> | WritableSignal<V> | V : T[P];
}>;
}
/**
* Type that the `mount` function returns
* @type MountResponse<T>
*/
type MountResponse<T> = {
/**
* Fixture for debugging and testing a component.
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture
*/
fixture: ComponentFixture<T>;
/**
* The instance of the root component class
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture#componentInstance
*/
component: T;
};
declare class CypressTestComponentRenderer extends TestComponentRenderer {
insertRootElement(rootElId: string): void;
removeAllRootElements(): void;
}
/**
* Mounts an Angular component inside Cypress browser
*
* @param component Angular component being mounted or its template
* @param config configuration used to configure the TestBed
* @example
* import { mount } from '@cypress/angular-signals'
* import { StepperComponent } from './stepper.component'
* import { MyService } from 'services/my.service'
* import { SharedModule } from 'shared/shared.module';
* it('mounts', () => {
* mount(StepperComponent, {
* providers: [MyService],
* imports: [SharedModule]
* })
* cy.get('[data-cy=increment]').click()
* cy.get('[data-cy=counter]').should('have.text', '1')
* })
*
* // or
*
* it('mounts with template', () => {
* mount('<app-stepper></app-stepper>', {
* declarations: [StepperComponent],
* })
* })
*
* @see {@link https://on.cypress.io/mounting-angular} for more details.
*
* @returns A component and component fixture
*/
declare function mount<T>(component: Type<T> | string, config?: MountConfig<T>): Cypress.Chainable<MountResponse<T>>;
/**
* Creates a new Event Emitter and then spies on it's `emit` method
*
* @param {string} alias name you want to use for your cy.spy() alias
* @returns EventEmitter<T>
* @example
* import { StepperComponent } from './stepper.component'
* import { mount, createOutputSpy } from '@cypress/angular-signals'
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { change: createOutputSpy('changeSpy') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@changeSpy').should('have.been.called')
* })
*
* // Or for use with Angular Signals following the output nomenclature.
* // see https://v17.angular.io/guide/model-inputs#differences-between-model-and-input/
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { count: signal(0), countChange: createOutputSpy('countChange') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@countChange').should('have.been.called')
* })
*/
declare const createOutputSpy: <T>(alias: string) => any;
export { CypressTestComponentRenderer, MountConfig, MountResponse, createOutputSpy, mount };

1861
node_modules/cypress/angular-signals/dist/index.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

74
node_modules/cypress/angular-signals/package.json generated vendored Normal file
View File

@@ -0,0 +1,74 @@
{
"name": "@cypress/angular-signals",
"version": "0.0.0-development",
"description": "Test Angular Components using Signals with Cypress",
"main": "dist/index.js",
"scripts": {
"prebuild": "rimraf dist",
"build": "rollup -c rollup.config.mjs",
"postbuild": "node ../../scripts/sync-exported-npm-with-cli.js",
"check-ts": "tsc --noEmit",
"dev": "rollup -c rollup.config.mjs -w",
"lint": "eslint --ext .js,.ts,.json, ."
},
"dependencies": {},
"devDependencies": {
"@angular/common": "^17.2.0",
"@angular/core": "^17.2.0",
"@angular/platform-browser-dynamic": "^17.2.0",
"@cypress/mount-utils": "0.0.0-development",
"typescript": "~5.4.5",
"zone.js": "~0.14.6"
},
"peerDependencies": {
"@angular/common": ">=17.2",
"@angular/core": ">=17.2",
"@angular/platform-browser-dynamic": ">=17.2",
"rxjs": ">=7.5.0",
"zone.js": ">=0.13.0"
},
"files": [
"dist"
],
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/blob/develop/npm/angular-signals/#readme",
"bugs": "https://github.com/cypress-io/cypress/issues/new?assignees=&labels=npm%3A%20%40cypress%2Fangular&template=1-bug-report.md&title=",
"keywords": [
"angular",
"cypress",
"cypress-io",
"test",
"testing"
],
"contributors": [
{
"name": "Bill Glesias",
"social": "@atofstryker"
}
],
"module": "dist/index.js",
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"outputs": [
"{workspaceRoot}/cli/angular-signals"
]
}
}
},
"standard": {
"globals": [
"Cypress",
"cy",
"expect"
]
}
}

10
node_modules/cypress/angular/README.md generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# @cypress/angular
Mount Angular components in the open source [Cypress.io](https://www.cypress.io/) test runner
> **Note:** This package is bundled with the `cypress` package and should not need to be installed separately. See the [Angular Component Testing Docs](https://docs.cypress.io/guides/component-testing/angular/overview) for mounting Angular components. Installing and importing `mount` from `@cypress/angular` should only be done for advanced use-cases.
## Development
Run `yarn build` to compile and sync packages to the `cypress` cli package.
## [Changelog](./CHANGELOG.md)

10
node_modules/cypress/angular/angular/README.md generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# @cypress/angular
Mount Angular components in the open source [Cypress.io](https://www.cypress.io/) test runner
> **Note:** This package is bundled with the `cypress` package and should not need to be installed separately. See the [Angular Component Testing Docs](https://docs.cypress.io/guides/component-testing/angular/overview) for mounting Angular components. Installing and importing `mount` from `@cypress/angular` should only be done for advanced use-cases.
## Development
Run `yarn build` to compile and sync packages to the `cypress` cli package.
## [Changelog](./CHANGELOG.md)

127
node_modules/cypress/angular/angular/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,127 @@
/// <reference types="cypress" />
import { Type } from '@angular/core';
import { TestModuleMetadata, ComponentFixture, TestComponentRenderer } from '@angular/core/testing';
/**
* Additional module configurations needed while mounting the component, like
* providers, declarations, imports and even component @Inputs()
*
* @interface MountConfig
* @see https://angular.io/api/core/testing/TestModuleMetadata
*/
interface MountConfig<T> extends TestModuleMetadata {
/**
* @memberof MountConfig
* @description flag to automatically create a cy.spy() for every component @Output() property
* @example
* export class ButtonComponent {
* @Output clicked = new EventEmitter()
* }
*
* cy.mount(ButtonComponent, { autoSpyOutputs: true })
* cy.get('@clickedSpy).should('have.been.called')
*/
autoSpyOutputs?: boolean;
/**
* @memberof MountConfig
* @description flag defaulted to true to automatically detect changes in your components
*/
autoDetectChanges?: boolean;
/**
* @memberof MountConfig
* @example
* import { ButtonComponent } from 'button/button.component'
* it('renders a button with Save text', () => {
* cy.mount(ButtonComponent, { componentProperties: { text: 'Save' }})
* cy.get('button').contains('Save')
* })
*
* it('renders a button with a cy.spy() replacing EventEmitter', () => {
* cy.mount(ButtonComponent, {
* componentProperties: {
* clicked: cy.spy().as('mySpy)
* }
* })
* cy.get('button').click()
* cy.get('@mySpy').should('have.been.called')
* })
*/
componentProperties?: Partial<{
[P in keyof T]: T[P];
}>;
}
/**
* Type that the `mount` function returns
* @type MountResponse<T>
*/
type MountResponse<T> = {
/**
* Fixture for debugging and testing a component.
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture
*/
fixture: ComponentFixture<T>;
/**
* The instance of the root component class
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture#componentInstance
*/
component: T;
};
declare class CypressTestComponentRenderer extends TestComponentRenderer {
insertRootElement(rootElId: string): void;
removeAllRootElements(): void;
}
/**
* Mounts an Angular component inside Cypress browser
*
* @param component Angular component being mounted or its template
* @param config configuration used to configure the TestBed
* @example
* import { mount } from '@cypress/angular'
* import { StepperComponent } from './stepper.component'
* import { MyService } from 'services/my.service'
* import { SharedModule } from 'shared/shared.module';
* it('mounts', () => {
* mount(StepperComponent, {
* providers: [MyService],
* imports: [SharedModule]
* })
* cy.get('[data-cy=increment]').click()
* cy.get('[data-cy=counter]').should('have.text', '1')
* })
*
* // or
*
* it('mounts with template', () => {
* mount('<app-stepper></app-stepper>', {
* declarations: [StepperComponent],
* })
* })
*
* @see {@link https://on.cypress.io/mounting-angular} for more details.
*
* @returns A component and component fixture
*/
declare function mount<T>(component: Type<T> | string, config?: MountConfig<T>): Cypress.Chainable<MountResponse<T>>;
/**
* Creates a new Event Emitter and then spies on it's `emit` method
*
* @param {string} alias name you want to use for your cy.spy() alias
* @returns EventEmitter<T>
* @example
* import { StepperComponent } from './stepper.component'
* import { mount, createOutputSpy } from '@cypress/angular'
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { change: createOutputSpy('changeSpy') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@changeSpy').should('have.been.called')
* })
*/
declare const createOutputSpy: <T>(alias: string) => any;
export { CypressTestComponentRenderer, MountConfig, MountResponse, createOutputSpy, mount };

340
node_modules/cypress/angular/angular/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,340 @@
/**
* @cypress/angular v0.0.0-development
* (c) 2024 Cypress.io
* Released under the MIT License
*/
import 'zone.js';
import 'zone.js/testing';
import { CommonModule } from '@angular/common';
import { Injectable, Component, EventEmitter, SimpleChange, ErrorHandler } from '@angular/core';
import { getTestBed, TestComponentRenderer, TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
const ROOT_SELECTOR = '[data-cy-root]';
/**
* Gets the root element used to mount the component.
* @returns {HTMLElement} The root element
* @throws {Error} If the root element is not found
*/
const getContainerEl = () => {
const el = document.querySelector(ROOT_SELECTOR);
if (el) {
return el;
}
throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`);
};
/**
* Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
* @param optionalCallback Callback to be called before the next test runs
*/
function setupHooks(optionalCallback) {
// We don't want CT side effects to run when e2e
// testing so we early return.
// System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
if (Cypress.testingType !== 'component') {
return;
}
// When running component specs, we cannot allow "cy.visit"
// because it will wipe out our preparation work, and does not make much sense
// thus we overwrite "cy.visit" to throw an error
Cypress.Commands.overwrite('visit', () => {
throw new Error('cy.visit from a component spec is not allowed');
});
Cypress.Commands.overwrite('session', () => {
throw new Error('cy.session from a component spec is not allowed');
});
Cypress.Commands.overwrite('origin', () => {
throw new Error('cy.origin from a component spec is not allowed');
});
// @ts-ignore
Cypress.on('test:before:after:run:async', () => {
optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
});
}
/**
* @hack fixes "Mocha has already been patched with Zone" error.
*/
// @ts-ignore
window.Mocha['__zone_patch__'] = false;
let activeFixture = null;
function cleanup() {
// Not public, we need to call this to remove the last component from the DOM
try {
getTestBed().tearDownTestingModule();
}
catch (e) {
const notSupportedError = new Error(`Failed to teardown component. The version of Angular you are using may not be officially supported.`);
notSupportedError.docsUrl = 'https://on.cypress.io/component-framework-configuration';
throw notSupportedError;
}
getTestBed().resetTestingModule();
activeFixture = null;
}
// 'zone.js/testing' is not properly aliasing `it.skip` but it does provide `xit`/`xspecify`
// Written up under https://github.com/angular/angular/issues/46297 but is not seeing movement
// so we'll patch here pending a fix in that library
// @ts-ignore Ignore so that way we can bypass semantic error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
globalThis.it.skip = globalThis.xit;
let CypressAngularErrorHandler = class CypressAngularErrorHandler {
handleError(error) {
throw error;
}
};
CypressAngularErrorHandler = __decorate([
Injectable()
], CypressAngularErrorHandler);
/**
* Bootstraps the TestModuleMetaData passed to the TestBed
*
* @param {Type<T>} component Angular component being mounted
* @param {MountConfig} config TestBed configuration passed into the mount function
* @returns {MountConfig} MountConfig
*/
function bootstrapModule(component, config) {
var _a;
const testModuleMetaData = __rest(config, ["componentProperties"]);
if (!testModuleMetaData.declarations) {
testModuleMetaData.declarations = [];
}
if (!testModuleMetaData.imports) {
testModuleMetaData.imports = [];
}
if (!testModuleMetaData.providers) {
testModuleMetaData.providers = [];
}
// Replace default error handler since it will swallow uncaught exceptions.
// We want these to be uncaught so Cypress catches it and fails the test
testModuleMetaData.providers.push({
provide: ErrorHandler,
useClass: CypressAngularErrorHandler,
});
// check if the component is a standalone component
if ((_a = component.ɵcmp) === null || _a === void 0 ? void 0 : _a.standalone) {
testModuleMetaData.imports.push(component);
}
else {
testModuleMetaData.declarations.push(component);
}
if (!testModuleMetaData.imports.includes(CommonModule)) {
testModuleMetaData.imports.push(CommonModule);
}
return testModuleMetaData;
}
let CypressTestComponentRenderer = class CypressTestComponentRenderer extends TestComponentRenderer {
insertRootElement(rootElId) {
this.removeAllRootElements();
const rootElement = getContainerEl();
rootElement.setAttribute('id', rootElId);
}
removeAllRootElements() {
getContainerEl().innerHTML = '';
}
};
CypressTestComponentRenderer = __decorate([
Injectable()
], CypressTestComponentRenderer);
/**
* Initializes the TestBed
*
* @param {Type<T> | string} component Angular component being mounted or its template
* @param {MountConfig} config TestBed configuration passed into the mount function
* @returns {Type<T>} componentFixture
*/
function initTestBed(component, config) {
const componentFixture = createComponentFixture(component);
getTestBed().configureTestingModule(Object.assign({}, bootstrapModule(componentFixture, config)));
getTestBed().overrideProvider(TestComponentRenderer, { useValue: new CypressTestComponentRenderer() });
return componentFixture;
}
let WrapperComponent = class WrapperComponent {
};
WrapperComponent = __decorate([
Component({ selector: 'cy-wrapper-component', template: '' })
], WrapperComponent);
/**
* Returns the Component if Type<T> or creates a WrapperComponent
*
* @param {Type<T> | string} component The component you want to create a fixture of
* @returns {Type<T> | WrapperComponent}
*/
function createComponentFixture(component) {
if (typeof component === 'string') {
// getTestBed().overrideTemplate is available in v14+
// The static TestBed.overrideTemplate is available across versions
TestBed.overrideTemplate(WrapperComponent, component);
return WrapperComponent;
}
return component;
}
/**
* Creates the ComponentFixture
*
* @param {Type<T>} component Angular component being mounted
* @param {MountConfig<T>} config MountConfig
* @returns {ComponentFixture<T>} ComponentFixture
*/
function setupFixture(component, config) {
const fixture = getTestBed().createComponent(component);
setupComponent(config, fixture);
fixture.whenStable().then(() => {
var _a;
fixture.autoDetectChanges((_a = config.autoDetectChanges) !== null && _a !== void 0 ? _a : true);
});
return fixture;
}
/**
* Gets the componentInstance and Object.assigns any componentProperties() passed in the MountConfig
*
* @param {MountConfig} config TestBed configuration passed into the mount function
* @param {ComponentFixture<T>} fixture Fixture for debugging and testing a component.
* @returns {T} Component being mounted
*/
function setupComponent(config, fixture) {
let component = fixture.componentInstance;
if (config === null || config === void 0 ? void 0 : config.componentProperties) {
component = Object.assign(component, config.componentProperties);
}
if (config.autoSpyOutputs) {
Object.keys(component).forEach((key) => {
const property = component[key];
if (property instanceof EventEmitter) {
component[key] = createOutputSpy(`${key}Spy`);
}
});
}
// Manually call ngOnChanges when mounting components using the class syntax.
// This is necessary because we are assigning input values to the class directly
// on mount and therefore the ngOnChanges() lifecycle is not triggered.
if (component.ngOnChanges && config.componentProperties) {
const { componentProperties } = config;
const simpleChanges = Object.entries(componentProperties).reduce((acc, [key, value]) => {
acc[key] = new SimpleChange(null, value, true);
return acc;
}, {});
if (Object.keys(componentProperties).length > 0) {
component.ngOnChanges(simpleChanges);
}
}
}
/**
* Mounts an Angular component inside Cypress browser
*
* @param component Angular component being mounted or its template
* @param config configuration used to configure the TestBed
* @example
* import { mount } from '@cypress/angular'
* import { StepperComponent } from './stepper.component'
* import { MyService } from 'services/my.service'
* import { SharedModule } from 'shared/shared.module';
* it('mounts', () => {
* mount(StepperComponent, {
* providers: [MyService],
* imports: [SharedModule]
* })
* cy.get('[data-cy=increment]').click()
* cy.get('[data-cy=counter]').should('have.text', '1')
* })
*
* // or
*
* it('mounts with template', () => {
* mount('<app-stepper></app-stepper>', {
* declarations: [StepperComponent],
* })
* })
*
* @see {@link https://on.cypress.io/mounting-angular} for more details.
*
* @returns A component and component fixture
*/
function mount(component, config = {}) {
// Remove last mounted component if cy.mount is called more than once in a test
if (activeFixture) {
cleanup();
}
const componentFixture = initTestBed(component, config);
activeFixture = setupFixture(componentFixture, config);
const mountResponse = {
fixture: activeFixture,
component: activeFixture.componentInstance,
};
const logMessage = typeof component === 'string' ? 'Component' : componentFixture.name;
Cypress.log({
name: 'mount',
message: logMessage,
consoleProps: () => ({ result: mountResponse }),
});
return cy.wrap(mountResponse, { log: false });
}
/**
* Creates a new Event Emitter and then spies on it's `emit` method
*
* @param {string} alias name you want to use for your cy.spy() alias
* @returns EventEmitter<T>
* @example
* import { StepperComponent } from './stepper.component'
* import { mount, createOutputSpy } from '@cypress/angular'
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { change: createOutputSpy('changeSpy') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@changeSpy').should('have.been.called')
* })
*/
const createOutputSpy = (alias) => {
const emitter = new EventEmitter();
cy.spy(emitter, 'emit').as(alias);
return emitter;
};
// Only needs to run once, we reset before each test
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false },
});
setupHooks(cleanup);
export { CypressTestComponentRenderer, createOutputSpy, mount };

76
node_modules/cypress/angular/angular/package.json generated vendored Normal file
View File

@@ -0,0 +1,76 @@
{
"name": "@cypress/angular",
"version": "0.0.0-development",
"description": "Test Angular Components using Cypress",
"main": "dist/index.js",
"scripts": {
"prebuild": "rimraf dist",
"build": "rollup -c rollup.config.mjs",
"postbuild": "node ../../scripts/sync-exported-npm-with-cli.js",
"check-ts": "tsc --noEmit",
"lint": "eslint --ext .js,.ts,.json, ."
},
"dependencies": {},
"devDependencies": {
"@angular/common": "^14.2.0",
"@angular/core": "^14.2.0",
"@angular/platform-browser-dynamic": "^14.2.0",
"@cypress/mount-utils": "0.0.0-development",
"typescript": "~5.4.5",
"zone.js": "~0.11.4"
},
"peerDependencies": {
"@angular/common": ">=13",
"@angular/core": ">=13",
"@angular/platform-browser-dynamic": ">=13",
"zone.js": ">=0.11.0"
},
"files": [
"dist"
],
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/blob/develop/npm/angular/#readme",
"bugs": "https://github.com/cypress-io/cypress/issues/new?assignees=&labels=npm%3A%20%40cypress%2Fangular&template=1-bug-report.md&title=",
"keywords": [
"angular",
"cypress",
"cypress-io",
"test",
"testing"
],
"contributors": [
{
"name": "Jordan Powell",
"social": "@jordanpowell88"
},
{
"name": "Zach Williams",
"social": "@ZachJW34"
}
],
"module": "dist/index.js",
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"outputs": [
"{workspaceRoot}/cli/angular"
]
}
}
},
"standard": {
"globals": [
"Cypress",
"cy",
"expect"
]
}
}

127
node_modules/cypress/angular/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,127 @@
/// <reference types="cypress" />
import { Type } from '@angular/core';
import { TestModuleMetadata, ComponentFixture, TestComponentRenderer } from '@angular/core/testing';
/**
* Additional module configurations needed while mounting the component, like
* providers, declarations, imports and even component @Inputs()
*
* @interface MountConfig
* @see https://angular.io/api/core/testing/TestModuleMetadata
*/
interface MountConfig<T> extends TestModuleMetadata {
/**
* @memberof MountConfig
* @description flag to automatically create a cy.spy() for every component @Output() property
* @example
* export class ButtonComponent {
* @Output clicked = new EventEmitter()
* }
*
* cy.mount(ButtonComponent, { autoSpyOutputs: true })
* cy.get('@clickedSpy).should('have.been.called')
*/
autoSpyOutputs?: boolean;
/**
* @memberof MountConfig
* @description flag defaulted to true to automatically detect changes in your components
*/
autoDetectChanges?: boolean;
/**
* @memberof MountConfig
* @example
* import { ButtonComponent } from 'button/button.component'
* it('renders a button with Save text', () => {
* cy.mount(ButtonComponent, { componentProperties: { text: 'Save' }})
* cy.get('button').contains('Save')
* })
*
* it('renders a button with a cy.spy() replacing EventEmitter', () => {
* cy.mount(ButtonComponent, {
* componentProperties: {
* clicked: cy.spy().as('mySpy)
* }
* })
* cy.get('button').click()
* cy.get('@mySpy').should('have.been.called')
* })
*/
componentProperties?: Partial<{
[P in keyof T]: T[P];
}>;
}
/**
* Type that the `mount` function returns
* @type MountResponse<T>
*/
type MountResponse<T> = {
/**
* Fixture for debugging and testing a component.
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture
*/
fixture: ComponentFixture<T>;
/**
* The instance of the root component class
*
* @memberof MountResponse
* @see https://angular.io/api/core/testing/ComponentFixture#componentInstance
*/
component: T;
};
declare class CypressTestComponentRenderer extends TestComponentRenderer {
insertRootElement(rootElId: string): void;
removeAllRootElements(): void;
}
/**
* Mounts an Angular component inside Cypress browser
*
* @param component Angular component being mounted or its template
* @param config configuration used to configure the TestBed
* @example
* import { mount } from '@cypress/angular'
* import { StepperComponent } from './stepper.component'
* import { MyService } from 'services/my.service'
* import { SharedModule } from 'shared/shared.module';
* it('mounts', () => {
* mount(StepperComponent, {
* providers: [MyService],
* imports: [SharedModule]
* })
* cy.get('[data-cy=increment]').click()
* cy.get('[data-cy=counter]').should('have.text', '1')
* })
*
* // or
*
* it('mounts with template', () => {
* mount('<app-stepper></app-stepper>', {
* declarations: [StepperComponent],
* })
* })
*
* @see {@link https://on.cypress.io/mounting-angular} for more details.
*
* @returns A component and component fixture
*/
declare function mount<T>(component: Type<T> | string, config?: MountConfig<T>): Cypress.Chainable<MountResponse<T>>;
/**
* Creates a new Event Emitter and then spies on it's `emit` method
*
* @param {string} alias name you want to use for your cy.spy() alias
* @returns EventEmitter<T>
* @example
* import { StepperComponent } from './stepper.component'
* import { mount, createOutputSpy } from '@cypress/angular'
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { change: createOutputSpy('changeSpy') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@changeSpy').should('have.been.called')
* })
*/
declare const createOutputSpy: <T>(alias: string) => any;
export { CypressTestComponentRenderer, MountConfig, MountResponse, createOutputSpy, mount };

340
node_modules/cypress/angular/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,340 @@
/**
* @cypress/angular v0.0.0-development
* (c) 2024 Cypress.io
* Released under the MIT License
*/
import 'zone.js';
import 'zone.js/testing';
import { CommonModule } from '@angular/common';
import { Injectable, Component, EventEmitter, SimpleChange, ErrorHandler } from '@angular/core';
import { getTestBed, TestComponentRenderer, TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/* global Reflect, Promise, SuppressedError, Symbol */
function __rest(s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
}
function __decorate(decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
const ROOT_SELECTOR = '[data-cy-root]';
/**
* Gets the root element used to mount the component.
* @returns {HTMLElement} The root element
* @throws {Error} If the root element is not found
*/
const getContainerEl = () => {
const el = document.querySelector(ROOT_SELECTOR);
if (el) {
return el;
}
throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`);
};
/**
* Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
* @param optionalCallback Callback to be called before the next test runs
*/
function setupHooks(optionalCallback) {
// We don't want CT side effects to run when e2e
// testing so we early return.
// System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
if (Cypress.testingType !== 'component') {
return;
}
// When running component specs, we cannot allow "cy.visit"
// because it will wipe out our preparation work, and does not make much sense
// thus we overwrite "cy.visit" to throw an error
Cypress.Commands.overwrite('visit', () => {
throw new Error('cy.visit from a component spec is not allowed');
});
Cypress.Commands.overwrite('session', () => {
throw new Error('cy.session from a component spec is not allowed');
});
Cypress.Commands.overwrite('origin', () => {
throw new Error('cy.origin from a component spec is not allowed');
});
// @ts-ignore
Cypress.on('test:before:after:run:async', () => {
optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
});
}
/**
* @hack fixes "Mocha has already been patched with Zone" error.
*/
// @ts-ignore
window.Mocha['__zone_patch__'] = false;
let activeFixture = null;
function cleanup() {
// Not public, we need to call this to remove the last component from the DOM
try {
getTestBed().tearDownTestingModule();
}
catch (e) {
const notSupportedError = new Error(`Failed to teardown component. The version of Angular you are using may not be officially supported.`);
notSupportedError.docsUrl = 'https://on.cypress.io/component-framework-configuration';
throw notSupportedError;
}
getTestBed().resetTestingModule();
activeFixture = null;
}
// 'zone.js/testing' is not properly aliasing `it.skip` but it does provide `xit`/`xspecify`
// Written up under https://github.com/angular/angular/issues/46297 but is not seeing movement
// so we'll patch here pending a fix in that library
// @ts-ignore Ignore so that way we can bypass semantic error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature.
globalThis.it.skip = globalThis.xit;
let CypressAngularErrorHandler = class CypressAngularErrorHandler {
handleError(error) {
throw error;
}
};
CypressAngularErrorHandler = __decorate([
Injectable()
], CypressAngularErrorHandler);
/**
* Bootstraps the TestModuleMetaData passed to the TestBed
*
* @param {Type<T>} component Angular component being mounted
* @param {MountConfig} config TestBed configuration passed into the mount function
* @returns {MountConfig} MountConfig
*/
function bootstrapModule(component, config) {
var _a;
const testModuleMetaData = __rest(config, ["componentProperties"]);
if (!testModuleMetaData.declarations) {
testModuleMetaData.declarations = [];
}
if (!testModuleMetaData.imports) {
testModuleMetaData.imports = [];
}
if (!testModuleMetaData.providers) {
testModuleMetaData.providers = [];
}
// Replace default error handler since it will swallow uncaught exceptions.
// We want these to be uncaught so Cypress catches it and fails the test
testModuleMetaData.providers.push({
provide: ErrorHandler,
useClass: CypressAngularErrorHandler,
});
// check if the component is a standalone component
if ((_a = component.ɵcmp) === null || _a === void 0 ? void 0 : _a.standalone) {
testModuleMetaData.imports.push(component);
}
else {
testModuleMetaData.declarations.push(component);
}
if (!testModuleMetaData.imports.includes(CommonModule)) {
testModuleMetaData.imports.push(CommonModule);
}
return testModuleMetaData;
}
let CypressTestComponentRenderer = class CypressTestComponentRenderer extends TestComponentRenderer {
insertRootElement(rootElId) {
this.removeAllRootElements();
const rootElement = getContainerEl();
rootElement.setAttribute('id', rootElId);
}
removeAllRootElements() {
getContainerEl().innerHTML = '';
}
};
CypressTestComponentRenderer = __decorate([
Injectable()
], CypressTestComponentRenderer);
/**
* Initializes the TestBed
*
* @param {Type<T> | string} component Angular component being mounted or its template
* @param {MountConfig} config TestBed configuration passed into the mount function
* @returns {Type<T>} componentFixture
*/
function initTestBed(component, config) {
const componentFixture = createComponentFixture(component);
getTestBed().configureTestingModule(Object.assign({}, bootstrapModule(componentFixture, config)));
getTestBed().overrideProvider(TestComponentRenderer, { useValue: new CypressTestComponentRenderer() });
return componentFixture;
}
let WrapperComponent = class WrapperComponent {
};
WrapperComponent = __decorate([
Component({ selector: 'cy-wrapper-component', template: '' })
], WrapperComponent);
/**
* Returns the Component if Type<T> or creates a WrapperComponent
*
* @param {Type<T> | string} component The component you want to create a fixture of
* @returns {Type<T> | WrapperComponent}
*/
function createComponentFixture(component) {
if (typeof component === 'string') {
// getTestBed().overrideTemplate is available in v14+
// The static TestBed.overrideTemplate is available across versions
TestBed.overrideTemplate(WrapperComponent, component);
return WrapperComponent;
}
return component;
}
/**
* Creates the ComponentFixture
*
* @param {Type<T>} component Angular component being mounted
* @param {MountConfig<T>} config MountConfig
* @returns {ComponentFixture<T>} ComponentFixture
*/
function setupFixture(component, config) {
const fixture = getTestBed().createComponent(component);
setupComponent(config, fixture);
fixture.whenStable().then(() => {
var _a;
fixture.autoDetectChanges((_a = config.autoDetectChanges) !== null && _a !== void 0 ? _a : true);
});
return fixture;
}
/**
* Gets the componentInstance and Object.assigns any componentProperties() passed in the MountConfig
*
* @param {MountConfig} config TestBed configuration passed into the mount function
* @param {ComponentFixture<T>} fixture Fixture for debugging and testing a component.
* @returns {T} Component being mounted
*/
function setupComponent(config, fixture) {
let component = fixture.componentInstance;
if (config === null || config === void 0 ? void 0 : config.componentProperties) {
component = Object.assign(component, config.componentProperties);
}
if (config.autoSpyOutputs) {
Object.keys(component).forEach((key) => {
const property = component[key];
if (property instanceof EventEmitter) {
component[key] = createOutputSpy(`${key}Spy`);
}
});
}
// Manually call ngOnChanges when mounting components using the class syntax.
// This is necessary because we are assigning input values to the class directly
// on mount and therefore the ngOnChanges() lifecycle is not triggered.
if (component.ngOnChanges && config.componentProperties) {
const { componentProperties } = config;
const simpleChanges = Object.entries(componentProperties).reduce((acc, [key, value]) => {
acc[key] = new SimpleChange(null, value, true);
return acc;
}, {});
if (Object.keys(componentProperties).length > 0) {
component.ngOnChanges(simpleChanges);
}
}
}
/**
* Mounts an Angular component inside Cypress browser
*
* @param component Angular component being mounted or its template
* @param config configuration used to configure the TestBed
* @example
* import { mount } from '@cypress/angular'
* import { StepperComponent } from './stepper.component'
* import { MyService } from 'services/my.service'
* import { SharedModule } from 'shared/shared.module';
* it('mounts', () => {
* mount(StepperComponent, {
* providers: [MyService],
* imports: [SharedModule]
* })
* cy.get('[data-cy=increment]').click()
* cy.get('[data-cy=counter]').should('have.text', '1')
* })
*
* // or
*
* it('mounts with template', () => {
* mount('<app-stepper></app-stepper>', {
* declarations: [StepperComponent],
* })
* })
*
* @see {@link https://on.cypress.io/mounting-angular} for more details.
*
* @returns A component and component fixture
*/
function mount(component, config = {}) {
// Remove last mounted component if cy.mount is called more than once in a test
if (activeFixture) {
cleanup();
}
const componentFixture = initTestBed(component, config);
activeFixture = setupFixture(componentFixture, config);
const mountResponse = {
fixture: activeFixture,
component: activeFixture.componentInstance,
};
const logMessage = typeof component === 'string' ? 'Component' : componentFixture.name;
Cypress.log({
name: 'mount',
message: logMessage,
consoleProps: () => ({ result: mountResponse }),
});
return cy.wrap(mountResponse, { log: false });
}
/**
* Creates a new Event Emitter and then spies on it's `emit` method
*
* @param {string} alias name you want to use for your cy.spy() alias
* @returns EventEmitter<T>
* @example
* import { StepperComponent } from './stepper.component'
* import { mount, createOutputSpy } from '@cypress/angular'
*
* it('Has spy', () => {
* mount(StepperComponent, { componentProperties: { change: createOutputSpy('changeSpy') } })
* cy.get('[data-cy=increment]').click()
* cy.get('@changeSpy').should('have.been.called')
* })
*/
const createOutputSpy = (alias) => {
const emitter = new EventEmitter();
cy.spy(emitter, 'emit').as(alias);
return emitter;
};
// Only needs to run once, we reset before each test
getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
teardown: { destroyAfterEach: false },
});
setupHooks(cleanup);
export { CypressTestComponentRenderer, createOutputSpy, mount };

76
node_modules/cypress/angular/package.json generated vendored Normal file
View File

@@ -0,0 +1,76 @@
{
"name": "@cypress/angular",
"version": "0.0.0-development",
"description": "Test Angular Components using Cypress",
"main": "dist/index.js",
"scripts": {
"prebuild": "rimraf dist",
"build": "rollup -c rollup.config.mjs",
"postbuild": "node ../../scripts/sync-exported-npm-with-cli.js",
"check-ts": "tsc --noEmit",
"lint": "eslint --ext .js,.ts,.json, ."
},
"dependencies": {},
"devDependencies": {
"@angular/common": "^14.2.0",
"@angular/core": "^14.2.0",
"@angular/platform-browser-dynamic": "^14.2.0",
"@cypress/mount-utils": "0.0.0-development",
"typescript": "~5.4.5",
"zone.js": "~0.11.4"
},
"peerDependencies": {
"@angular/common": ">=13",
"@angular/core": ">=13",
"@angular/platform-browser-dynamic": ">=13",
"zone.js": ">=0.11.0"
},
"files": [
"dist"
],
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/blob/develop/npm/angular/#readme",
"bugs": "https://github.com/cypress-io/cypress/issues/new?assignees=&labels=npm%3A%20%40cypress%2Fangular&template=1-bug-report.md&title=",
"keywords": [
"angular",
"cypress",
"cypress-io",
"test",
"testing"
],
"contributors": [
{
"name": "Jordan Powell",
"social": "@jordanpowell88"
},
{
"name": "Zach Williams",
"social": "@ZachJW34"
}
],
"module": "dist/index.js",
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"outputs": [
"{workspaceRoot}/cli/angular"
]
}
}
},
"standard": {
"globals": [
"Cypress",
"cy",
"expect"
]
}
}

3
node_modules/cypress/bin/cypress generated vendored Normal file
View File

@@ -0,0 +1,3 @@
#!/usr/bin/env node
require('../lib/cli').init()

27
node_modules/cypress/index.js generated vendored Normal file
View File

@@ -0,0 +1,27 @@
"use strict";
const minimist = require('minimist');
const debug = require('debug')('cypress:cli');
const args = minimist(process.argv.slice(2));
const util = require('./lib/util');
// we're being used from the command line
switch (args.exec) {
case 'install':
debug('installing Cypress from NPM');
require('./lib/tasks/install').start({
force: args.force
}).catch(util.logErrorExit1);
break;
case 'verify':
// for simple testing in the monorepo
debug('verifying Cypress');
require('./lib/tasks/verify').start({
force: true
}) // always force verification
.catch(util.logErrorExit1);
break;
default:
debug('exporting Cypress module interface');
module.exports = require('./lib/cypress');
}

17
node_modules/cypress/index.mjs generated vendored Normal file
View File

@@ -0,0 +1,17 @@
import module from 'module'
const require = module.createRequire(import.meta.url)
const cypress = require('./lib/cypress')
export default cypress
export const defineConfig = cypress.defineConfig
export const defineComponentFramework = cypress.defineComponentFramework
export const run = cypress.run
export const open = cypress.open
export const cli = cypress.cli

58
node_modules/cypress/lib/VerboseRenderer.js generated vendored Normal file
View File

@@ -0,0 +1,58 @@
"use strict";
// Vendored from @cypress/listr-verbose-renderer
const figures = require('figures');
const cliCursor = require('cli-cursor');
const chalk = require('chalk');
const dayjs = require('dayjs');
const formattedLog = (options, output) => {
const timestamp = dayjs().format(options.dateFormat);
// eslint-disable-next-line no-console
console.log(`${chalk.dim(`[${timestamp}]`)} ${output}`);
};
const renderHelper = (task, event, options) => {
const log = formattedLog.bind(undefined, options);
if (event.type === 'STATE') {
const message = task.isPending() ? 'started' : task.state;
log(`${task.title} [${message}]`);
if (task.isSkipped() && task.output) {
log(`${figures.arrowRight} ${task.output}`);
}
} else if (event.type === 'TITLE') {
log(`${task.title} [title changed]`);
}
};
const render = (tasks, options) => {
for (const task of tasks) {
task.subscribe(event => {
if (event.type === 'SUBTASKS') {
render(task.subtasks, options);
return;
}
renderHelper(task, event, options);
}, err => {
// eslint-disable-next-line no-console
console.log(err);
});
}
};
class VerboseRenderer {
constructor(tasks, options) {
this._tasks = tasks;
this._options = Object.assign({
dateFormat: 'HH:mm:ss'
}, options);
}
static get nonTTY() {
return true;
}
render() {
cliCursor.hide();
render(this._tasks, this._options);
}
end() {
cliCursor.show();
}
}
module.exports = VerboseRenderer;

440
node_modules/cypress/lib/cli.js generated vendored Normal file
View File

@@ -0,0 +1,440 @@
"use strict";
// @ts-check
const _ = require('lodash');
const commander = require('commander');
const {
stripIndent
} = require('common-tags');
const logSymbols = require('log-symbols');
const debug = require('debug')('cypress:cli:cli');
const util = require('./util');
const logger = require('./logger');
const errors = require('./errors');
const cache = require('./tasks/cache');
// patch "commander" method called when a user passed an unknown option
// we want to print help for the current command and exit with an error
function unknownOption(flag, type = 'option') {
if (this._allowUnknownOption) return;
logger.error();
logger.error(` error: unknown ${type}:`, flag);
logger.error();
this.outputHelp();
util.exit(1);
}
commander.Command.prototype.unknownOption = unknownOption;
const coerceFalse = arg => {
return arg !== 'false';
};
const coerceAnyStringToInt = arg => {
return typeof arg === 'string' ? parseInt(arg) : arg;
};
const spaceDelimitedArgsMsg = (flag, args) => {
let msg = `
${logSymbols.warning} Warning: It looks like you're passing --${flag} a space-separated list of arguments:
"${args.join(' ')}"
This will work, but it's not recommended.
If you are trying to pass multiple arguments, separate them with commas instead:
cypress run --${flag} arg1,arg2,arg3
`;
if (flag === 'spec') {
msg += `
The most common cause of this warning is using an unescaped glob pattern. If you are
trying to pass a glob pattern, escape it using quotes:
cypress run --spec "**/*.spec.js"
`;
}
logger.log();
logger.warn(stripIndent(msg));
logger.log();
};
const parseVariableOpts = (fnArgs, args) => {
const [opts, unknownArgs] = fnArgs;
if (unknownArgs && unknownArgs.length && (opts.spec || opts.tag)) {
// this will capture space-delimited args after
// flags that could have possible multiple args
// but before the next option
// --spec spec1 spec2 or --tag foo bar
const multiArgFlags = _.compact([opts.spec ? 'spec' : opts.spec, opts.tag ? 'tag' : opts.tag]);
_.forEach(multiArgFlags, flag => {
const argIndex = _.indexOf(args, `--${flag}`) + 2;
const nextOptOffset = _.findIndex(_.slice(args, argIndex), arg => {
return _.startsWith(arg, '--');
});
const endIndex = nextOptOffset !== -1 ? argIndex + nextOptOffset : args.length;
const maybeArgs = _.slice(args, argIndex, endIndex);
const extraArgs = _.intersection(maybeArgs, unknownArgs);
if (extraArgs.length) {
opts[flag] = [opts[flag]].concat(extraArgs);
spaceDelimitedArgsMsg(flag, opts[flag]);
opts[flag] = opts[flag].join(',');
}
});
}
debug('variable-length opts parsed %o', {
args,
opts
});
return util.parseOpts(opts);
};
const descriptions = {
autoCancelAfterFailures: 'overrides the project-level Cloud configuration to set the failed test threshold for auto cancellation or to disable auto cancellation when recording to the Cloud',
browser: 'runs Cypress in the browser with the given name. if a filesystem path is supplied, Cypress will attempt to use the browser at that path.',
cacheClear: 'delete all cached binaries',
cachePrune: 'deletes all cached binaries except for the version currently in use',
cacheList: 'list cached binary versions',
cachePath: 'print the path to the binary cache',
cacheSize: 'Used with the list command to show the sizes of the cached folders',
ciBuildId: 'the unique identifier for a run on your CI provider. typically a "BUILD_ID" env var. this value is automatically detected for most CI providers',
component: 'runs component tests',
config: 'sets configuration values. separate multiple values with a comma. overrides any value in cypress.config.{js,ts,mjs,cjs}.',
configFile: 'path to script file where configuration values are set. defaults to "cypress.config.{js,ts,mjs,cjs}".',
detached: 'runs Cypress application in detached mode',
dev: 'runs cypress in development and bypasses binary check',
e2e: 'runs end to end tests',
env: 'sets environment variables. separate multiple values with a comma. overrides any value in cypress.config.{js,ts,mjs,cjs} or cypress.env.json',
exit: 'keep the browser open after tests finish',
forceInstall: 'force install the Cypress binary',
global: 'force Cypress into global mode as if its globally installed',
group: 'a named group for recorded runs in Cypress Cloud',
headed: 'displays the browser instead of running headlessly',
headless: 'hide the browser instead of running headed (default for cypress run)',
key: 'your secret Record Key. you can omit this if you set a CYPRESS_RECORD_KEY environment variable.',
parallel: 'enables concurrent runs and automatic load balancing of specs across multiple machines or processes',
port: 'runs Cypress on a specific port. overrides any value in cypress.config.{js,ts,mjs,cjs}.',
project: 'path to the project',
quiet: 'run quietly, using only the configured reporter',
record: 'records the run. sends test results, screenshots and videos to Cypress Cloud.',
reporter: 'runs a specific mocha reporter. pass a path to use a custom reporter. defaults to "spec"',
reporterOptions: 'options for the mocha reporter. defaults to "null"',
runnerUi: 'displays the Cypress Runner UI',
noRunnerUi: 'hides the Cypress Runner UI',
spec: 'runs specific spec file(s). defaults to "all"',
tag: 'named tag(s) for recorded runs in Cypress Cloud',
version: 'prints Cypress version'
};
const knownCommands = ['cache', 'help', '-h', '--help', 'install', 'open', 'run', 'open-ct', 'run-ct', 'verify', '-v', '--version', 'version', 'info'];
const text = description => {
if (!descriptions[description]) {
throw new Error(`Could not find description for: ${description}`);
}
return descriptions[description];
};
function includesVersion(args) {
return _.includes(args, '--version') || _.includes(args, '-v');
}
function showVersions(opts) {
debug('printing Cypress version');
debug('additional arguments %o', opts);
debug('parsed version arguments %o', opts);
const reportAllVersions = versions => {
logger.always('Cypress package version:', versions.package);
logger.always('Cypress binary version:', versions.binary);
logger.always('Electron version:', versions.electronVersion);
logger.always('Bundled Node version:', versions.electronNodeVersion);
};
const reportComponentVersion = (componentName, versions) => {
const names = {
package: 'package',
binary: 'binary',
electron: 'electronVersion',
node: 'electronNodeVersion'
};
if (!names[componentName]) {
throw new Error(`Unknown component name "${componentName}"`);
}
const name = names[componentName];
if (!versions[name]) {
throw new Error(`Cannot find version for component "${componentName}" under property "${name}"`);
}
const version = versions[name];
logger.always(version);
};
const defaultVersions = {
package: undefined,
binary: undefined,
electronVersion: undefined,
electronNodeVersion: undefined
};
return require('./exec/versions').getVersions().then((versions = defaultVersions) => {
if (opts !== null && opts !== void 0 && opts.component) {
reportComponentVersion(opts.component, versions);
} else {
reportAllVersions(versions);
}
process.exit(0);
}).catch(util.logErrorExit1);
}
const createProgram = () => {
const program = new commander.Command();
// bug in commander not printing name
// in usage help docs
program._name = 'cypress';
program.usage('<command> [options]');
return program;
};
const addCypressRunCommand = program => {
return program.command('run').usage('[options]').description('Runs Cypress tests from the CLI without the GUI').option('--auto-cancel-after-failures <test-failure-count || false>', text('autoCancelAfterFailures')).option('-b, --browser <browser-name-or-path>', text('browser')).option('--ci-build-id <id>', text('ciBuildId')).option('--component', text('component')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('--e2e', text('e2e')).option('-e, --env <env>', text('env')).option('--group <name>', text('group')).option('-k, --key <record-key>', text('key')).option('--headed', text('headed')).option('--headless', text('headless')).option('--no-exit', text('exit')).option('--parallel', text('parallel')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('-q, --quiet', text('quiet')).option('--record [bool]', text('record'), coerceFalse).option('-r, --reporter <reporter>', text('reporter')).option('--runner-ui', text('runnerUi')).option('--no-runner-ui', text('noRunnerUi')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-s, --spec <spec>', text('spec')).option('-t, --tag <tag>', text('tag')).option('--dev', text('dev'), coerceFalse);
};
const addCypressOpenCommand = program => {
return program.command('open').usage('[options]').description('Opens Cypress in the interactive GUI.').option('-b, --browser <browser-path>', text('browser')).option('--component', text('component')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-d, --detached [bool]', text('detached'), coerceFalse).option('--e2e', text('e2e')).option('-e, --env <env>', text('env')).option('--global', text('global')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('--dev', text('dev'), coerceFalse);
};
const maybeAddInspectFlags = program => {
if (process.argv.includes('--dev')) {
return program.option('--inspect', 'Node option').option('--inspect-brk', 'Node option');
}
return program;
};
/**
* Casts known command line options for "cypress run" to their intended type.
* For example if the user passes "--port 5005" the ".port" property should be
* a number 5005 and not a string "5005".
*
* Returns a clone of the original object.
*/
const castCypressOptions = opts => {
// only properties that have type "string | false" in our TS definition
// require special handling, because CLI parsing takes care of purely
// boolean arguments
const castOpts = {
...opts
};
if (_.has(opts, 'port')) {
castOpts.port = coerceAnyStringToInt(opts.port);
}
return castOpts;
};
module.exports = {
/**
* Parses `cypress run` command line option array into an object
* with options that you can feed into a `cypress.run()` module API call.
* @example
* const options = parseRunCommand(['cypress', 'run', '--browser', 'chrome'])
* // options is {browser: 'chrome'}
*/
parseRunCommand(args) {
return new Promise((resolve, reject) => {
if (!Array.isArray(args)) {
return reject(new Error('Expected array of arguments'));
}
// make a copy of the input arguments array
// and add placeholders where "node ..." would usually be
// also remove "cypress" keyword at the start if present
const cliArgs = args[0] === 'cypress' ? [...args.slice(1)] : [...args];
cliArgs.unshift(null, null);
debug('creating program parser');
const program = createProgram();
maybeAddInspectFlags(addCypressRunCommand(program)).action((...fnArgs) => {
debug('parsed Cypress run %o', fnArgs);
const options = parseVariableOpts(fnArgs, cliArgs);
debug('parsed options %o', options);
const casted = castCypressOptions(options);
debug('casted options %o', casted);
resolve(casted);
});
debug('parsing args: %o', cliArgs);
program.parse(cliArgs);
});
},
/**
* Parses `cypress open` command line option array into an object
* with options that you can feed into cy.openModeSystemTest test calls
* @example
* const options = parseOpenCommand(['cypress', 'open', '--browser', 'chrome'])
* // options is {browser: 'chrome'}
*/
parseOpenCommand(args) {
return new Promise((resolve, reject) => {
if (!Array.isArray(args)) {
return reject(new Error('Expected array of arguments'));
}
// make a copy of the input arguments array
// and add placeholders where "node ..." would usually be
// also remove "cypress" keyword at the start if present
const cliArgs = args[0] === 'cypress' ? [...args.slice(1)] : [...args];
cliArgs.unshift(null, null);
debug('creating program parser');
const program = createProgram();
maybeAddInspectFlags(addCypressOpenCommand(program)).action((...fnArgs) => {
debug('parsed Cypress open %o', fnArgs);
const options = parseVariableOpts(fnArgs, cliArgs);
debug('parsed options %o', options);
const casted = castCypressOptions(options);
debug('casted options %o', casted);
resolve(casted);
});
debug('parsing args: %o', cliArgs);
program.parse(cliArgs);
});
},
/**
* Parses the command line and kicks off Cypress process.
*/
init(args) {
if (!args) {
args = process.argv;
}
const {
CYPRESS_INTERNAL_ENV,
CYPRESS_DOWNLOAD_USE_CA
} = process.env;
if (process.env.CYPRESS_DOWNLOAD_USE_CA) {
let msg = `
${logSymbols.warning} Warning: It looks like you're setting CYPRESS_DOWNLOAD_USE_CA=${CYPRESS_DOWNLOAD_USE_CA}
The environment variable "CYPRESS_DOWNLOAD_USE_CA" is no longer required to be set.
You can safely unset this environment variable.
`;
logger.log();
logger.warn(stripIndent(msg));
logger.log();
}
if (!util.isValidCypressInternalEnvValue(CYPRESS_INTERNAL_ENV)) {
debug('invalid CYPRESS_INTERNAL_ENV value', CYPRESS_INTERNAL_ENV);
return errors.exitWithError(errors.errors.invalidCypressEnv)(`CYPRESS_INTERNAL_ENV=${CYPRESS_INTERNAL_ENV}`);
}
if (util.isNonProductionCypressInternalEnvValue(CYPRESS_INTERNAL_ENV)) {
debug('non-production CYPRESS_INTERNAL_ENV value', CYPRESS_INTERNAL_ENV);
let msg = `
${logSymbols.warning} Warning: It looks like you're passing CYPRESS_INTERNAL_ENV=${CYPRESS_INTERNAL_ENV}
The environment variable "CYPRESS_INTERNAL_ENV" is reserved and should only be used internally.
Unset the "CYPRESS_INTERNAL_ENV" environment variable and run Cypress again.
`;
logger.log();
logger.warn(stripIndent(msg));
logger.log();
}
const program = createProgram();
program.command('help').description('Shows CLI help and exits').action(() => {
program.help();
});
const handleVersion = cmd => {
return cmd.option('--component <package|binary|electron|node>', 'component to report version for').action((opts, ...other) => {
showVersions(util.parseOpts(opts));
});
};
handleVersion(program.storeOptionsAsProperties().option('-v, --version', text('version')).command('version').description(text('version')));
maybeAddInspectFlags(addCypressOpenCommand(program)).action(opts => {
debug('opening Cypress');
require('./exec/open').start(util.parseOpts(opts)).then(util.exit).catch(util.logErrorExit1);
});
maybeAddInspectFlags(addCypressRunCommand(program)).action((...fnArgs) => {
debug('running Cypress with args %o', fnArgs);
require('./exec/run').start(parseVariableOpts(fnArgs, args)).then(util.exit).catch(util.logErrorExit1);
});
program.command('open-ct').usage('[options]').description('Opens Cypress component testing interactive mode. Deprecated: use "open --component"').option('-b, --browser <browser-path>', text('browser')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-d, --detached [bool]', text('detached'), coerceFalse).option('-e, --env <env>', text('env')).option('--global', text('global')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('--dev', text('dev'), coerceFalse).action(opts => {
debug('opening Cypress');
const msg = `
${logSymbols.warning} Warning: open-ct is deprecated and will be removed in a future release.
Use \`cypress open --component\` instead.
`;
logger.warn();
logger.warn(stripIndent(msg));
logger.warn();
require('./exec/open').start({
...util.parseOpts(opts),
testingType: 'component'
}).then(util.exit).catch(util.logErrorExit1);
});
program.command('run-ct').usage('[options]').description('Runs all Cypress component testing suites. Deprecated: use "run --component"').option('-b, --browser <browser-name-or-path>', text('browser')).option('--ci-build-id <id>', text('ciBuildId')).option('-c, --config <config>', text('config')).option('-C, --config-file <config-file>', text('configFile')).option('-e, --env <env>', text('env')).option('--group <name>', text('group')).option('-k, --key <record-key>', text('key')).option('--headed', text('headed')).option('--headless', text('headless')).option('--no-exit', text('exit')).option('--parallel', text('parallel')).option('-p, --port <port>', text('port')).option('-P, --project <project-path>', text('project')).option('-q, --quiet', text('quiet')).option('--record [bool]', text('record'), coerceFalse).option('-r, --reporter <reporter>', text('reporter')).option('-o, --reporter-options <reporter-options>', text('reporterOptions')).option('-s, --spec <spec>', text('spec')).option('-t, --tag <tag>', text('tag')).option('--dev', text('dev'), coerceFalse).action(opts => {
debug('running Cypress run-ct');
const msg = `
${logSymbols.warning} Warning: run-ct is deprecated and will be removed in a future release.
Use \`cypress run --component\` instead.
`;
logger.warn();
logger.warn(stripIndent(msg));
logger.warn();
require('./exec/run').start({
...util.parseOpts(opts),
testingType: 'component'
}).then(util.exit).catch(util.logErrorExit1);
});
program.command('install').usage('[options]').description('Installs the Cypress executable matching this package\'s version').option('-f, --force', text('forceInstall')).action(opts => {
require('./tasks/install').start(util.parseOpts(opts)).catch(util.logErrorExit1);
});
program.command('verify').usage('[options]').description('Verifies that Cypress is installed correctly and executable').option('--dev', text('dev'), coerceFalse).action(opts => {
const defaultOpts = {
force: true,
welcomeMessage: false
};
const parsedOpts = util.parseOpts(opts);
const options = _.extend(parsedOpts, defaultOpts);
require('./tasks/verify').start(options).catch(util.logErrorExit1);
});
program.command('cache').usage('[command]').description('Manages the Cypress binary cache').option('list', text('cacheList')).option('path', text('cachePath')).option('clear', text('cacheClear')).option('prune', text('cachePrune')).option('--size', text('cacheSize')).action(function (opts, args) {
if (!args || !args.length) {
this.outputHelp();
util.exit(1);
}
const [command] = args;
if (!_.includes(['list', 'path', 'clear', 'prune'], command)) {
unknownOption.call(this, `cache ${command}`, 'command');
}
if (command === 'list') {
debug('cache command %o', {
command,
size: opts.size
});
return cache.list(opts.size).catch({
code: 'ENOENT'
}, () => {
logger.always('No cached binary versions were found.');
process.exit(0);
}).catch(e => {
debug('cache list command failed with "%s"', e.message);
util.logErrorExit1(e);
});
}
cache[command]();
});
program.command('info').usage('[command]').description('Prints Cypress and system information').option('--dev', text('dev'), coerceFalse).action(opts => {
require('./exec/info').start(opts).then(util.exit).catch(util.logErrorExit1);
});
debug('cli starts with arguments %j', args);
util.printNodeOptions();
// if there are no arguments
if (args.length <= 2) {
debug('printing help');
program.help();
// exits
}
const firstCommand = args[2];
if (!_.includes(knownCommands, firstCommand)) {
debug('unknown command %s', firstCommand);
logger.error('Unknown command', `"${firstCommand}"`);
program.outputHelp();
return util.exit(1);
}
if (includesVersion(args)) {
// commander 2.11.0 changes behavior
// and now does not understand top level options
// .option('-v, --version').command('version')
// so we have to manually catch '-v, --version'
handleVersion(program);
}
debug('program parsing arguments');
return program.parse(args);
}
};
// @ts-ignore
if (!module.parent) {
logger.error('This CLI module should be required from another Node module');
logger.error('and not executed directly');
process.exit(-1);
}

98
node_modules/cypress/lib/cypress.js generated vendored Normal file
View File

@@ -0,0 +1,98 @@
"use strict";
// https://github.com/cypress-io/cypress/issues/316
const Promise = require('bluebird');
const tmp = Promise.promisifyAll(require('tmp'));
const fs = require('./fs');
const open = require('./exec/open');
const run = require('./exec/run');
const util = require('./util');
const cli = require('./cli');
const cypressModuleApi = {
/**
* Opens Cypress GUI
* @see https://on.cypress.io/module-api#cypress-open
*/
open(options = {}) {
options = util.normalizeModuleOptions(options);
return open.start(options);
},
/**
* Runs Cypress tests in the current project
* @see https://on.cypress.io/module-api#cypress-run
*/
run(options = {}) {
if (!run.isValidProject(options.project)) {
return Promise.reject(new Error(`Invalid project path parameter: ${options.project}`));
}
options = util.normalizeModuleOptions(options);
tmp.setGracefulCleanup();
return tmp.fileAsync().then(outputPath => {
options.outputPath = outputPath;
return run.start(options).then(failedTests => {
return fs.readJsonAsync(outputPath, {
throws: false
}).then(output => {
if (!output) {
return {
status: 'failed',
failures: failedTests,
message: 'Could not find Cypress test run results'
};
}
return output;
});
});
});
},
cli: {
/**
* Parses CLI arguments into an object that you can pass to "cypress.run"
* @example
* const cypress = require('cypress')
* const cli = ['cypress', 'run', '--browser', 'firefox']
* const options = await cypress.cli.parseRunArguments(cli)
* // options is {browser: 'firefox'}
* await cypress.run(options)
* @see https://on.cypress.io/module-api
*/
parseRunArguments(args) {
return cli.parseRunCommand(args);
}
},
/**
* Provides automatic code completion for configuration in many popular code editors.
* While it's not strictly necessary for Cypress to parse your configuration, we
* recommend wrapping your config object with `defineConfig()`
* @example
* module.exports = defineConfig({
* viewportWith: 400
* })
*
* @see ../types/cypress-npm-api.d.ts
* @param {Cypress.ConfigOptions} config
* @returns {Cypress.ConfigOptions} the configuration passed in parameter
*/
defineConfig(config) {
return config;
},
/**
* Provides automatic code completion for Component Frameworks Definitions.
* While it's not strictly necessary for Cypress to parse your configuration, we
* recommend wrapping your Component Framework Definition object with `defineComponentFramework()`
* @example
* module.exports = defineComponentFramework({
* type: 'cypress-ct-solid-js'
* // ...
* })
*
* @see ../types/cypress-npm-api.d.ts
* @param {Cypress.ThirdPartyComponentFrameworkDefinition} config
* @returns {Cypress.ThirdPartyComponentFrameworkDefinition} the configuration passed in parameter
*/
defineComponentFramework(config) {
return config;
}
};
module.exports = cypressModuleApi;

392
node_modules/cypress/lib/errors.js generated vendored Normal file
View File

@@ -0,0 +1,392 @@
"use strict";
const chalk = require('chalk');
const {
stripIndent,
stripIndents
} = require('common-tags');
const la = require('lazy-ass');
const is = require('check-more-types');
const util = require('./util');
const state = require('./tasks/state');
const docsUrl = 'https://on.cypress.io';
const requiredDependenciesUrl = `${docsUrl}/required-dependencies`;
const runDocumentationUrl = `${docsUrl}/cypress-run`;
// TODO it would be nice if all error objects could be enforced via types
// to only have description + solution properties
const hr = '----------';
const genericErrorSolution = stripIndent`
Search for an existing issue or open a GitHub issue at
${chalk.blue(util.issuesUrl)}
`;
// common errors Cypress application can encounter
const unknownError = {
description: 'Unknown Cypress CLI error',
solution: genericErrorSolution
};
const invalidRunProjectPath = {
description: 'Invalid --project path',
solution: stripIndent`
Please provide a valid project path.
Learn more about ${chalk.cyan('cypress run')} at:
${chalk.blue(runDocumentationUrl)}
`
};
const invalidOS = {
description: 'The Cypress App could not be installed. Your machine does not meet the operating system requirements.',
solution: stripIndent`
${chalk.blue('https://on.cypress.io/guides/getting-started/installing-cypress#system-requirements')}`
};
const failedDownload = {
description: 'The Cypress App could not be downloaded.',
solution: stripIndent`
Does your workplace require a proxy to be used to access the Internet? If so, you must configure the HTTP_PROXY environment variable before downloading Cypress. Read more: https://on.cypress.io/proxy-configuration
Otherwise, please check network connectivity and try again:`
};
const failedUnzip = {
description: 'The Cypress App could not be unzipped.',
solution: genericErrorSolution
};
const failedUnzipWindowsMaxPathLength = {
description: 'The Cypress App could not be unzipped.',
solution: `This is most likely because the maximum path length is being exceeded on your system.
Read here for solutions to this problem: https://on.cypress.io/win-max-path-length-error`
};
const missingApp = binaryDir => {
return {
description: `No version of Cypress is installed in: ${chalk.cyan(binaryDir)}`,
solution: stripIndent`
\nPlease reinstall Cypress by running: ${chalk.cyan('cypress install')}
`
};
};
const binaryNotExecutable = executable => {
return {
description: `Cypress cannot run because this binary file does not have executable permissions here:\n\n${executable}`,
solution: stripIndent`\n
Reasons this may happen:
- node was installed as 'root' or with 'sudo'
- the cypress npm package as 'root' or with 'sudo'
Please check that you have the appropriate user permissions.
You can also try clearing the cache with 'cypress cache clear' and reinstalling.
`
};
};
const notInstalledCI = executable => {
return {
description: 'The cypress npm package is installed, but the Cypress binary is missing.',
solution: stripIndent`\n
We expected the binary to be installed here: ${chalk.cyan(executable)}
Reasons it may be missing:
- You're caching 'node_modules' but are not caching this path: ${util.getCacheDir()}
- You ran 'npm install' at an earlier build step but did not persist: ${util.getCacheDir()}
Properly caching the binary will fix this error and avoid downloading and unzipping Cypress.
Alternatively, you can run 'cypress install' to download the binary again.
${chalk.blue('https://on.cypress.io/not-installed-ci-error')}
`
};
};
const nonZeroExitCodeXvfb = {
description: 'Xvfb exited with a non zero exit code.',
solution: stripIndent`
There was a problem spawning Xvfb.
This is likely a problem with your system, permissions, or installation of Xvfb.
`
};
const missingXvfb = {
description: 'Your system is missing the dependency: Xvfb',
solution: stripIndent`
Install Xvfb and run Cypress again.
Read our documentation on dependencies for more information:
${chalk.blue(requiredDependenciesUrl)}
If you are using Docker, we provide containers with all required dependencies installed.
`
};
const smokeTestFailure = (smokeTestCommand, timedOut) => {
return {
description: `Cypress verification ${timedOut ? 'timed out' : 'failed'}.`,
solution: stripIndent`
This command failed with the following output:
${smokeTestCommand}
`
};
};
const invalidSmokeTestDisplayError = {
code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR',
description: 'Cypress verification failed.',
solution(msg) {
return stripIndent`
Cypress failed to start after spawning a new Xvfb server.
The error logs we received were:
${hr}
${msg}
${hr}
This may be due to a missing library or dependency. ${chalk.blue(requiredDependenciesUrl)}
Please refer to the error above for more detail.
`;
}
};
const missingDependency = {
description: 'Cypress failed to start.',
// this message is too Linux specific
solution: stripIndent`
This may be due to a missing library or dependency. ${chalk.blue(requiredDependenciesUrl)}
Please refer to the error below for more details.
`
};
const invalidCacheDirectory = {
description: 'Cypress cannot write to the cache directory due to file permissions',
solution: stripIndent`
See discussion and possible solutions at
${chalk.blue(util.getGitHubIssueUrl(1281))}
`
};
const versionMismatch = {
description: 'Installed version does not match package version.',
solution: 'Install Cypress and verify app again'
};
const incompatibleHeadlessFlags = {
description: '`--headed` and `--headless` cannot both be passed.',
solution: 'Either pass `--headed` or `--headless`, but not both.'
};
const solutionUnknown = stripIndent`
Please search Cypress documentation for possible solutions:
${chalk.blue(docsUrl)}
Check if there is a GitHub issue describing this crash:
${chalk.blue(util.issuesUrl)}
Consider opening a new issue.
`;
const unexpected = {
description: 'An unexpected error occurred while verifying the Cypress executable.',
solution: solutionUnknown
};
const invalidCypressEnv = {
description: chalk.red('The environment variable with the reserved name "CYPRESS_INTERNAL_ENV" is set.'),
solution: chalk.red('Unset the "CYPRESS_INTERNAL_ENV" environment variable and run Cypress again.'),
exitCode: 11
};
const invalidTestingType = {
description: 'Invalid testingType',
solution: `Please provide a valid testingType. Valid test types are ${chalk.cyan('\'e2e\'')} and ${chalk.cyan('\'component\'')}.`
};
const incompatibleTestTypeFlags = {
description: '`--e2e` and `--component` cannot both be passed.',
solution: 'Either pass `--e2e` or `--component`, but not both.'
};
const incompatibleTestingTypeAndFlag = {
description: 'Set a `testingType` and also passed `--e2e` or `--component` flags.',
solution: 'Either set `testingType` or pass a testing type flag, but not both.'
};
const invalidConfigFile = {
description: '`--config-file` cannot be false.',
solution: 'Either pass a relative path to a valid Cypress config file or remove this option.'
};
/**
* This error happens when CLI detects that the child Test Runner process
* was killed with a signal, like SIGBUS
* @see https://github.com/cypress-io/cypress/issues/5808
* @param {'close'|'event'} eventName Child close event name
* @param {string} signal Signal that closed the child process, like "SIGBUS"
*/
const childProcessKilled = (eventName, signal) => {
return {
description: `The Test Runner unexpectedly exited via a ${chalk.cyan(eventName)} event with signal ${chalk.cyan(signal)}`,
solution: solutionUnknown
};
};
const CYPRESS_RUN_BINARY = {
notValid: value => {
const properFormat = `**/${state.getPlatformExecutable()}`;
return {
description: `Could not run binary set by environment variable: CYPRESS_RUN_BINARY=${value}`,
solution: `Ensure the environment variable is a path to the Cypress binary, matching ${properFormat}`
};
}
};
function addPlatformInformation(info) {
return util.getPlatformInfo().then(platform => {
return {
...info,
platform
};
});
}
/**
* Given an error object (see the errors above), forms error message text with details,
* then resolves with Error instance you can throw or reject with.
* @param {object} errorObject
* @returns {Promise<Error>} resolves with an Error
* @example
```js
// inside a Promise with "resolve" and "reject"
const errorObject = childProcessKilled('exit', 'SIGKILL')
return getError(errorObject).then(reject)
```
*/
function getError(errorObject) {
return formErrorText(errorObject).then(errorMessage => {
const err = new Error(errorMessage);
err.known = true;
return err;
});
}
/**
* Forms nice error message with error and platform information,
* and if possible a way to solve it. Resolves with a string.
*/
function formErrorText(info, msg, prevMessage) {
return addPlatformInformation(info).then(obj => {
const formatted = [];
function add(msg) {
formatted.push(stripIndents(msg));
}
la(is.unemptyString(obj.description), 'expected error description to be text', obj.description);
// assuming that if there the solution is a function it will handle
// error message and (optional previous error message)
if (is.fn(obj.solution)) {
const text = obj.solution(msg, prevMessage);
la(is.unemptyString(text), 'expected solution to be text', text);
add(`
${obj.description}
${text}
`);
} else {
la(is.unemptyString(obj.solution), 'expected error solution to be text', obj.solution);
add(`
${obj.description}
${obj.solution}
`);
if (msg) {
add(`
${hr}
${msg}
`);
}
}
add(`
${hr}
${obj.platform}
`);
if (obj.footer) {
add(`
${hr}
${obj.footer}
`);
}
return formatted.join('\n\n');
});
}
const raise = info => {
return text => {
const err = new Error(text);
if (info.code) {
err.code = info.code;
}
err.known = true;
throw err;
};
};
const throwFormErrorText = info => {
return (msg, prevMessage) => {
return formErrorText(info, msg, prevMessage).then(raise(info));
};
};
/**
* Forms full error message with error and OS details, prints to the error output
* and then exits the process.
* @param {ErrorInformation} info Error information {description, solution}
* @example return exitWithError(errors.invalidCypressEnv)('foo')
*/
const exitWithError = info => {
return msg => {
return formErrorText(info, msg).then(text => {
// eslint-disable-next-line no-console
console.error(text);
process.exit(info.exitCode || 1);
});
};
};
module.exports = {
raise,
exitWithError,
// formError,
formErrorText,
throwFormErrorText,
getError,
hr,
errors: {
unknownError,
nonZeroExitCodeXvfb,
missingXvfb,
missingApp,
notInstalledCI,
missingDependency,
invalidOS,
invalidSmokeTestDisplayError,
versionMismatch,
binaryNotExecutable,
unexpected,
failedDownload,
failedUnzip,
failedUnzipWindowsMaxPathLength,
invalidCypressEnv,
invalidCacheDirectory,
CYPRESS_RUN_BINARY,
smokeTestFailure,
childProcessKilled,
incompatibleHeadlessFlags,
invalidRunProjectPath,
invalidTestingType,
incompatibleTestTypeFlags,
incompatibleTestingTypeAndFlag,
invalidConfigFile
}
};

92
node_modules/cypress/lib/exec/info.js generated vendored Normal file
View File

@@ -0,0 +1,92 @@
"use strict";
/* eslint-disable no-console */
const spawn = require('./spawn');
const util = require('../util');
const state = require('../tasks/state');
const os = require('os');
const chalk = require('chalk');
const prettyBytes = require('pretty-bytes');
const _ = require('lodash');
// color for numbers and show values
const g = chalk.green;
// color for paths
const p = chalk.cyan;
const red = chalk.red;
// urls
const link = chalk.blue.underline;
// to be exported
const methods = {};
methods.findProxyEnvironmentVariables = () => {
return _.pick(process.env, ['HTTP_PROXY', 'HTTPS_PROXY', 'NO_PROXY']);
};
const maskSensitiveVariables = obj => {
const masked = {
...obj
};
if (masked.CYPRESS_RECORD_KEY) {
masked.CYPRESS_RECORD_KEY = '<redacted>';
}
return masked;
};
methods.findCypressEnvironmentVariables = () => {
const isCyVariable = (val, key) => key.startsWith('CYPRESS_');
return _.pickBy(process.env, isCyVariable);
};
const formatCypressVariables = () => {
const vars = methods.findCypressEnvironmentVariables();
return maskSensitiveVariables(vars);
};
methods.start = async (options = {}) => {
const args = ['--mode=info'];
await spawn.start(args, {
dev: options.dev
});
console.log();
const proxyVars = methods.findProxyEnvironmentVariables();
if (_.isEmpty(proxyVars)) {
console.log('Proxy Settings: none detected');
} else {
console.log('Proxy Settings:');
_.forEach(proxyVars, (value, key) => {
console.log('%s: %s', key, g(value));
});
console.log();
console.log('Learn More: %s', link('https://on.cypress.io/proxy-configuration'));
console.log();
}
const cyVars = formatCypressVariables();
if (_.isEmpty(cyVars)) {
console.log('Environment Variables: none detected');
} else {
console.log('Environment Variables:');
_.forEach(cyVars, (value, key) => {
console.log('%s: %s', key, g(value));
});
}
console.log();
console.log('Application Data:', p(util.getApplicationDataFolder()));
console.log('Browser Profiles:', p(util.getApplicationDataFolder('browsers')));
console.log('Binary Caches: %s', p(state.getCacheDir()));
console.log();
const osVersion = await util.getOsVersionAsync();
const buildInfo = util.pkgBuildInfo();
const isStable = buildInfo && buildInfo.stable;
console.log('Cypress Version: %s', g(util.pkgVersion()), isStable ? g('(stable)') : red('(pre-release)'));
console.log('System Platform: %s (%s)', g(os.platform()), g(osVersion));
console.log('System Memory: %s free %s', g(prettyBytes(os.totalmem())), g(prettyBytes(os.freemem())));
if (!buildInfo) {
console.log();
console.log('This is the', red('development'), '(un-built) Cypress CLI.');
} else if (!isStable) {
console.log();
console.log('This is a', red('pre-release'), 'build of Cypress.');
console.log('Build info:');
console.log(' Commit SHA:', g(buildInfo.commitSha));
console.log(' Commit Branch:', g(buildInfo.commitBranch));
console.log(' Commit Date:', g(buildInfo.commitDate));
}
};
module.exports = methods;

90
node_modules/cypress/lib/exec/open.js generated vendored Normal file
View File

@@ -0,0 +1,90 @@
"use strict";
const debug = require('debug')('cypress:cli');
const util = require('../util');
const spawn = require('./spawn');
const verify = require('../tasks/verify');
const {
processTestingType,
checkConfigFile
} = require('./shared');
const {
exitWithError
} = require('../errors');
/**
* Maps options collected by the CLI
* and forms list of CLI arguments to the server.
*
* Note: there is lightweight validation, with errors
* thrown synchronously.
*
* @returns {string[]} list of CLI arguments
*/
const processOpenOptions = (options = {}) => {
// In addition to setting the project directory, setting the project option
// here ultimately decides whether cypress is run in global mode or not.
// It's first based off whether it's installed globally by npm/yarn (-g).
// A global install can be overridden by the --project flag, putting Cypress
// in project mode. A non-global install can be overridden by the --global
// flag, putting it in global mode.
if (!util.isInstalledGlobally() && !options.global && !options.project) {
options.project = process.cwd();
}
const args = [];
if (options.config) {
args.push('--config', options.config);
}
if (options.configFile !== undefined) {
checkConfigFile(options);
args.push('--config-file', options.configFile);
}
if (options.browser) {
args.push('--browser', options.browser);
}
if (options.env) {
args.push('--env', options.env);
}
if (options.port) {
args.push('--port', options.port);
}
if (options.project) {
args.push('--project', options.project);
}
if (options.global) {
args.push('--global', options.global);
}
if (options.inspect) {
args.push('--inspect');
}
if (options.inspectBrk) {
args.push('--inspectBrk');
}
args.push(...processTestingType(options));
debug('opening from options %j', options);
debug('command line arguments %j', args);
return args;
};
module.exports = {
processOpenOptions,
start(options = {}) {
function open() {
try {
const args = processOpenOptions(options);
return spawn.start(args, {
dev: options.dev,
detached: Boolean(options.detached)
});
} catch (err) {
if (err.details) {
return exitWithError(err.details)();
}
throw err;
}
}
if (options.dev) {
return open();
}
return verify.start().then(open);
}
};

176
node_modules/cypress/lib/exec/run.js generated vendored Normal file
View File

@@ -0,0 +1,176 @@
"use strict";
const _ = require('lodash');
const debug = require('debug')('cypress:cli:run');
const util = require('../util');
const spawn = require('./spawn');
const verify = require('../tasks/verify');
const {
exitWithError,
errors
} = require('../errors');
const {
processTestingType,
throwInvalidOptionError,
checkConfigFile
} = require('./shared');
/**
* Typically a user passes a string path to the project.
* But "cypress open" allows using `false` to open in global mode,
* and the user can accidentally execute `cypress run --project false`
* which should be invalid.
*/
const isValidProject = v => {
if (typeof v === 'boolean') {
return false;
}
if (v === '' || v === 'false' || v === 'true') {
return false;
}
return true;
};
/**
* Maps options collected by the CLI
* and forms list of CLI arguments to the server.
*
* Note: there is lightweight validation, with errors
* thrown synchronously.
*
* @returns {string[]} list of CLI arguments
*/
const processRunOptions = (options = {}) => {
debug('processing run options %o', options);
if (!isValidProject(options.project)) {
debug('invalid project option %o', {
project: options.project
});
return throwInvalidOptionError(errors.invalidRunProjectPath);
}
const args = ['--run-project', options.project];
if (options.autoCancelAfterFailures || options.autoCancelAfterFailures === 0 || options.autoCancelAfterFailures === false) {
args.push('--auto-cancel-after-failures', options.autoCancelAfterFailures);
}
if (options.browser) {
args.push('--browser', options.browser);
}
if (options.ciBuildId) {
args.push('--ci-build-id', options.ciBuildId);
}
if (options.config) {
args.push('--config', options.config);
}
if (options.configFile !== undefined) {
checkConfigFile(options);
args.push('--config-file', options.configFile);
}
if (options.env) {
args.push('--env', options.env);
}
if (options.exit === false) {
args.push('--no-exit');
}
if (options.group) {
args.push('--group', options.group);
}
if (options.headed) {
args.push('--headed', options.headed);
}
if (options.headless) {
if (options.headed) {
return throwInvalidOptionError(errors.incompatibleHeadlessFlags);
}
args.push('--headed', !options.headless);
}
// if key is set use that - else attempt to find it by environment variable
if (options.key == null) {
debug('--key is not set, looking up environment variable CYPRESS_RECORD_KEY');
options.key = util.getEnv('CYPRESS_RECORD_KEY');
}
// if we have a key assume we're in record mode
if (options.key) {
args.push('--key', options.key);
}
if (options.outputPath) {
args.push('--output-path', options.outputPath);
}
if (options.parallel) {
args.push('--parallel');
}
if (options.port) {
args.push('--port', options.port);
}
if (options.quiet) {
args.push('--quiet');
}
// if record is defined and we're not
// already in ci mode, then send it up
if (options.record != null) {
args.push('--record', options.record);
}
// if we have a specific reporter push that into the args
if (options.reporter) {
args.push('--reporter', options.reporter);
}
// if we have a specific reporter push that into the args
if (options.reporterOptions) {
args.push('--reporter-options', options.reporterOptions);
}
if (options.runnerUi != null) {
args.push('--runner-ui', options.runnerUi);
}
// if we have specific spec(s) push that into the args
if (options.spec) {
args.push('--spec', options.spec);
}
if (options.tag) {
args.push('--tag', options.tag);
}
if (options.inspect) {
args.push('--inspect');
}
if (options.inspectBrk) {
args.push('--inspectBrk');
}
args.push(...processTestingType(options));
return args;
};
module.exports = {
processRunOptions,
isValidProject,
// resolves with the number of failed tests
start(options = {}) {
_.defaults(options, {
key: null,
spec: null,
reporter: null,
reporterOptions: null,
project: process.cwd()
});
function run() {
try {
const args = processRunOptions(options);
debug('run to spawn.start args %j', args);
return spawn.start(args, {
dev: options.dev
});
} catch (err) {
if (err.details) {
return exitWithError(err.details)();
}
throw err;
}
}
if (options.dev) {
return run();
}
return verify.start().then(run);
}
};

62
node_modules/cypress/lib/exec/shared.js generated vendored Normal file
View File

@@ -0,0 +1,62 @@
"use strict";
const {
errors
} = require('../errors');
/**
* Throws an error with "details" property from
* "errors" object.
* @param {Object} details - Error details
*/
const throwInvalidOptionError = details => {
if (!details) {
details = errors.unknownError;
}
// throw this error synchronously, it will be caught later on and
// the details will be propagated to the promise chain
const err = new Error();
err.details = details;
throw err;
};
/**
* Selects exec args based on the configured `testingType`
* @param {string} testingType The type of tests being executed
* @returns {string[]} The array of new exec arguments
*/
const processTestingType = options => {
if (options.e2e && options.component) {
return throwInvalidOptionError(errors.incompatibleTestTypeFlags);
}
if (options.testingType && (options.component || options.e2e)) {
return throwInvalidOptionError(errors.incompatibleTestTypeFlags);
}
if (options.testingType === 'component' || options.component || options.ct) {
return ['--testing-type', 'component'];
}
if (options.testingType === 'e2e' || options.e2e) {
return ['--testing-type', 'e2e'];
}
if (options.testingType) {
return throwInvalidOptionError(errors.invalidTestingType);
}
return [];
};
/**
* Throws an error if configFile is string 'false' or boolean false
* @param {*} options
*/
const checkConfigFile = options => {
// CLI will parse as string, module API can pass in boolean
if (options.configFile === 'false' || options.configFile === false) {
throwInvalidOptionError(errors.invalidConfigFile);
}
};
module.exports = {
throwInvalidOptionError,
processTestingType,
checkConfigFile
};

306
node_modules/cypress/lib/exec/spawn.js generated vendored Normal file
View File

@@ -0,0 +1,306 @@
"use strict";
const _ = require('lodash');
const os = require('os');
const cp = require('child_process');
const path = require('path');
const Promise = require('bluebird');
const debug = require('debug')('cypress:cli');
const debugVerbose = require('debug')('cypress-verbose:cli');
const util = require('../util');
const state = require('../tasks/state');
const xvfb = require('./xvfb');
const verify = require('../tasks/verify');
const errors = require('../errors');
const isXlibOrLibudevRe = /^(?:Xlib|libudev)/;
const isHighSierraWarningRe = /\*\*\* WARNING/;
const isRenderWorkerRe = /\.RenderWorker-/;
// Chromium (which Electron uses) always makes several attempts to connect to the system dbus.
// This works fine in most desktop environments, but in a docker container, there is no dbus service
// and Chromium emits several error lines, similar to these:
// [1957:0406/160550.146820:ERROR:bus.cc(392)] Failed to connect to the bus: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
// [1957:0406/160550.147994:ERROR:bus.cc(392)] Failed to connect to the bus: Address does not contain a colon
// These warnings are absolutely harmless. Failure to connect to dbus means that electron won't be able to access the user's
// credential wallet (none exists in a docker container) and won't show up in the system tray (again, none exists).
// Failure to connect is expected and normal here, but users frequently misidentify these errors as the cause of their problems.
// https://github.com/cypress-io/cypress/issues/19299
const isDbusWarning = /Failed to connect to the bus:/;
// Electron began logging these on self-signed certs with 17.0.0-alpha.4.
// Once this is fixed upstream this regex can be removed: https://github.com/electron/electron/issues/34583
// Sample:
// [3801:0606/152837.383892:ERROR:cert_verify_proc_builtin.cc(681)] CertVerifyProcBuiltin for www.googletagmanager.com failed:
// ----- Certificate i=0 (OU=Cypress Proxy Server Certificate,O=Cypress Proxy CA,L=Internet,ST=Internet,C=Internet,CN=www.googletagmanager.com) -----
// ERROR: No matching issuer found
const isCertVerifyProcBuiltin = /(^\[.*ERROR:cert_verify_proc_builtin\.cc|^----- Certificate i=0 \(OU=Cypress Proxy|^ERROR: No matching issuer found$)/;
// Electron logs a benign warning about WebSwapCGLLayer on MacOS v12 and Electron v18 due to a naming collision in shared libraries.
// Once this is fixed upstream this regex can be removed: https://github.com/electron/electron/issues/33685
// Sample:
// objc[60540]: Class WebSwapCGLLayer is implemented in both /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Frameworks/libANGLE-shared.dylib (0x7ffa5a006318) and /{path/to/app}/node_modules/electron/dist/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libGLESv2.dylib (0x10f8a89c8). One of the two will be used. Which one is undefined.
const isMacOSElectronWebSwapCGLLayerWarning = /^objc\[\d+\]: Class WebSwapCGLLayer is implemented in both.*Which one is undefined\./;
/**
* Electron logs benign warnings about Vulkan when run on hosts that do not have a GPU. This is coming from the primary Electron process,
* and not the browser being used for tests.
* Samples:
* Warning: loader_scanned_icd_add: Driver /usr/lib/x86_64-linux-gnu/libvulkan_intel.so supports Vulkan 1.2, but only supports loader interface version 4. Interface version 5 or newer required to support this version of Vulkan (Policy #LDP_DRIVER_7)
* Warning: loader_scanned_icd_add: Driver /usr/lib/x86_64-linux-gnu/libvulkan_lvp.so supports Vulkan 1.1, but only supports loader interface version 4. Interface version 5 or newer required to support this version of Vulkan (Policy #LDP_DRIVER_7)
* Warning: loader_scanned_icd_add: Driver /usr/lib/x86_64-linux-gnu/libvulkan_radeon.so supports Vulkan 1.2, but only supports loader interface version 4. Interface version 5 or newer required to support this verison of Vulkan (Policy #LDP_DRIVER_7)
* Warning: Layer VK_LAYER_MESA_device_select uses API version 1.2 which is older than the application specified API version of 1.3. May cause issues.
*/
const isHostVulkanDriverWarning = /^Warning:.+(#LDP_DRIVER_7|VK_LAYER_MESA_device_select).+/;
/**
* Electron logs benign warnings about Vulkan when run in docker containers whose host does not have a GPU. This is coming from the primary
* Electron process, and not the browser being used for tests.
* Sample:
* Warning: vkCreateInstance: Found no drivers!
* Warning: vkCreateInstance failed with VK_ERROR_INCOMPATIBLE_DRIVER
* at CheckVkSuccessImpl (../../third_party/dawn/src/dawn/native/vulkan/VulkanError.cpp:88)
* at CreateVkInstance (../../third_party/dawn/src/dawn/native/vulkan/BackendVk.cpp:458)
* at Initialize (../../third_party/dawn/src/dawn/native/vulkan/BackendVk.cpp:344)
* at Create (../../third_party/dawn/src/dawn/native/vulkan/BackendVk.cpp:266)
* at operator() (../../third_party/dawn/src/dawn/native/vulkan/BackendVk.cpp:521)
*/
const isContainerVulkanDriverWarning = /^Warning: vkCreateInstance/;
const isContainerVulkanStack = /^\s*at (CheckVkSuccessImpl|CreateVkInstance|Initialize|Create|operator).+(VulkanError|BackendVk).cpp/;
const GARBAGE_WARNINGS = [isXlibOrLibudevRe, isHighSierraWarningRe, isRenderWorkerRe, isDbusWarning, isCertVerifyProcBuiltin, isMacOSElectronWebSwapCGLLayerWarning, isHostVulkanDriverWarning, isContainerVulkanDriverWarning, isContainerVulkanStack];
const isGarbageLineWarning = str => {
return _.some(GARBAGE_WARNINGS, re => {
return re.test(str);
});
};
function isPlatform(platform) {
return os.platform() === platform;
}
function needsStderrPiped(needsXvfb) {
return _.some([isPlatform('darwin'), needsXvfb && isPlatform('linux'), util.isPossibleLinuxWithIncorrectDisplay()]);
}
function needsEverythingPipedDirectly() {
return isPlatform('win32');
}
function getStdio(needsXvfb) {
if (needsEverythingPipedDirectly()) {
return 'pipe';
}
// https://github.com/cypress-io/cypress/issues/921
// https://github.com/cypress-io/cypress/issues/1143
// https://github.com/cypress-io/cypress/issues/1745
if (needsStderrPiped(needsXvfb)) {
// returning pipe here so we can massage stderr
// and remove garbage from Xlib and libuv
// due to starting the Xvfb process on linux
return ['inherit', 'inherit', 'pipe'];
}
return 'inherit';
}
module.exports = {
isGarbageLineWarning,
start(args, options = {}) {
const needsXvfb = xvfb.isNeeded();
let executable = state.getPathToExecutable(state.getBinaryDir());
if (util.getEnv('CYPRESS_RUN_BINARY')) {
executable = path.resolve(util.getEnv('CYPRESS_RUN_BINARY'));
}
debug('needs to start own Xvfb?', needsXvfb);
// Always push cwd into the args
// which additionally acts as a signal to the
// binary that it was invoked through the NPM module
args = args || [];
if (typeof args === 'string') {
args = [args];
}
args = [...args, '--cwd', process.cwd(), '--userNodePath', process.execPath, '--userNodeVersion', process.versions.node];
_.defaults(options, {
dev: false,
env: process.env,
detached: false,
stdio: getStdio(needsXvfb)
});
const spawn = (overrides = {}) => {
return new Promise((resolve, reject) => {
_.defaults(overrides, {
onStderrData: false
});
const {
onStderrData
} = overrides;
const envOverrides = util.getEnvOverrides(options);
const electronArgs = [];
const node11WindowsFix = isPlatform('win32');
let startScriptPath;
if (options.dev) {
executable = 'node';
// if we're in dev then reset
// the launch cmd to be 'npm run dev'
startScriptPath = path.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js'), debug('in dev mode the args became %o', args);
}
if (!options.dev && verify.needsSandbox()) {
electronArgs.push('--no-sandbox');
}
// strip dev out of child process options
/**
* @type {import('child_process').ForkOptions}
*/
let stdioOptions = _.pick(options, 'env', 'detached', 'stdio');
// figure out if we're going to be force enabling or disabling colors.
// also figure out whether we should force stdout and stderr into thinking
// it is a tty as opposed to a pipe.
stdioOptions.env = _.extend({}, stdioOptions.env, envOverrides);
if (node11WindowsFix) {
stdioOptions = _.extend({}, stdioOptions, {
windowsHide: false
});
}
if (util.isPossibleLinuxWithIncorrectDisplay()) {
// make sure we use the latest DISPLAY variable if any
debug('passing DISPLAY', process.env.DISPLAY);
stdioOptions.env.DISPLAY = process.env.DISPLAY;
}
if (stdioOptions.env.ELECTRON_RUN_AS_NODE) {
// Since we are running electron as node, we need to add an entry point file.
startScriptPath = path.join(state.getBinaryPkgPath(path.dirname(executable)), '..', 'index.js');
} else {
// Start arguments with "--" so Electron knows these are OUR
// arguments and does not try to sanitize them. Otherwise on Windows
// an url in one of the arguments crashes it :(
// https://github.com/cypress-io/cypress/issues/5466
args = [...electronArgs, '--', ...args];
}
if (startScriptPath) {
args.unshift(startScriptPath);
}
if (process.env.CYPRESS_INTERNAL_DEV_DEBUG) {
args.unshift(process.env.CYPRESS_INTERNAL_DEV_DEBUG);
}
debug('spawn args %o %o', args, _.omit(stdioOptions, 'env'));
debug('spawning Cypress with executable: %s', executable);
const child = cp.spawn(executable, args, stdioOptions);
function resolveOn(event) {
return function (code, signal) {
debug('child event fired %o', {
event,
code,
signal
});
if (code === null) {
const errorObject = errors.errors.childProcessKilled(event, signal);
return errors.getError(errorObject).then(reject);
}
resolve(code);
};
}
child.on('close', resolveOn('close'));
child.on('exit', resolveOn('exit'));
child.on('error', reject);
// if stdio options is set to 'pipe', then
// we should set up pipes:
// process STDIN (read stream) => child STDIN (writeable)
// child STDOUT => process STDOUT
// child STDERR => process STDERR with additional filtering
if (child.stdin) {
debug('piping process STDIN into child STDIN');
process.stdin.pipe(child.stdin);
}
if (child.stdout) {
debug('piping child STDOUT to process STDOUT');
child.stdout.pipe(process.stdout);
}
// if this is defined then we are manually piping for linux
// to filter out the garbage
if (child.stderr) {
debug('piping child STDERR to process STDERR');
child.stderr.on('data', data => {
const str = data.toString();
// bail if this is warning line garbage
if (isGarbageLineWarning(str)) {
debugVerbose(str);
return;
}
// if we have a callback and this explicitly returns
// false then bail
if (onStderrData && onStderrData(str)) {
return;
}
// else pass it along!
process.stderr.write(data);
});
}
// https://github.com/cypress-io/cypress/issues/1841
// https://github.com/cypress-io/cypress/issues/5241
// In some versions of node, it will throw on windows
// when you close the parent process after piping
// into the child process. unpiping does not seem
// to have any effect. so we're just catching the
// error here and not doing anything.
process.stdin.on('error', err => {
if (['EPIPE', 'ENOTCONN'].includes(err.code)) {
return;
}
throw err;
});
if (stdioOptions.detached) {
child.unref();
}
});
};
const spawnInXvfb = () => {
return xvfb.start().then(userFriendlySpawn).finally(xvfb.stop);
};
const userFriendlySpawn = linuxWithDisplayEnv => {
debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
let brokenGtkDisplay;
const overrides = {};
if (linuxWithDisplayEnv) {
_.extend(overrides, {
electronLogging: true,
onStderrData(str) {
// if we receive a broken pipe anywhere
// then we know that's why cypress exited early
if (util.isBrokenGtkDisplay(str)) {
brokenGtkDisplay = true;
}
}
});
}
return spawn(overrides).then(code => {
if (code !== 0 && brokenGtkDisplay) {
util.logBrokenGtkDisplayWarning();
return spawnInXvfb();
}
return code;
})
// we can format and handle an error message from the code above
// prevent wrapping error again by using "known: undefined" filter
.catch({
known: undefined
}, errors.throwFormErrorText(errors.errors.unexpected));
};
if (needsXvfb) {
return spawnInXvfb();
}
// if we are on linux and there's already a DISPLAY
// set, then we may need to rerun cypress after
// spawning our own Xvfb server
const linuxWithDisplayEnv = util.isPossibleLinuxWithIncorrectDisplay();
return userFriendlySpawn(linuxWithDisplayEnv);
}
};

53
node_modules/cypress/lib/exec/versions.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
"use strict";
const Promise = require('bluebird');
const debug = require('debug')('cypress:cli');
const path = require('path');
const util = require('../util');
const state = require('../tasks/state');
const {
throwFormErrorText,
errors
} = require('../errors');
const getVersions = () => {
return Promise.try(() => {
if (util.getEnv('CYPRESS_RUN_BINARY')) {
let envBinaryPath = path.resolve(util.getEnv('CYPRESS_RUN_BINARY'));
return state.parseRealPlatformBinaryFolderAsync(envBinaryPath).then(envBinaryDir => {
if (!envBinaryDir) {
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
}
debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
return envBinaryDir;
}).catch({
code: 'ENOENT'
}, err => {
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(err.message);
});
}
return state.getBinaryDir();
}).then(state.getBinaryPkgAsync).then(pkg => {
const versions = {
binary: state.getBinaryPkgVersion(pkg),
electronVersion: state.getBinaryElectronVersion(pkg),
electronNodeVersion: state.getBinaryElectronNodeVersion(pkg)
};
debug('binary versions %o', versions);
return versions;
}).then(binaryVersions => {
const buildInfo = util.pkgBuildInfo();
let packageVersion = util.pkgVersion();
if (!buildInfo) packageVersion += ' (development)';else if (!buildInfo.stable) packageVersion += ' (pre-release)';
const versions = {
package: packageVersion,
binary: binaryVersions.binary || 'not installed',
electronVersion: binaryVersions.electronVersion || 'not found',
electronNodeVersion: binaryVersions.electronNodeVersion || 'not found'
};
debug('combined versions %o', versions);
return versions;
});
};
module.exports = {
getVersions
};

93
node_modules/cypress/lib/exec/xvfb.js generated vendored Normal file
View File

@@ -0,0 +1,93 @@
"use strict";
const os = require('os');
const Promise = require('bluebird');
const Xvfb = require('@cypress/xvfb');
const {
stripIndent
} = require('common-tags');
const Debug = require('debug');
const {
throwFormErrorText,
errors
} = require('../errors');
const util = require('../util');
const debug = Debug('cypress:cli');
const debugXvfb = Debug('cypress:xvfb');
debug.Debug = debugXvfb.Debug = Debug;
const xvfbOptions = {
displayNum: process.env.XVFB_DISPLAY_NUM,
timeout: 30000,
// milliseconds
// need to explicitly define screen otherwise electron will crash
// https://github.com/cypress-io/cypress/issues/6184
xvfb_args: ['-screen', '0', '1280x1024x24'],
onStderrData(data) {
if (debugXvfb.enabled) {
debugXvfb(data.toString());
}
}
};
const xvfb = Promise.promisifyAll(new Xvfb(xvfbOptions));
module.exports = {
_debugXvfb: debugXvfb,
// expose for testing
_xvfb: xvfb,
// expose for testing
_xvfbOptions: xvfbOptions,
// expose for testing
start() {
debug('Starting Xvfb');
return xvfb.startAsync().return(null).catch({
nonZeroExitCode: true
}, throwFormErrorText(errors.nonZeroExitCodeXvfb)).catch(err => {
if (err.known) {
throw err;
}
return throwFormErrorText(errors.missingXvfb)(err);
});
},
stop() {
debug('Stopping Xvfb');
return xvfb.stopAsync().return(null).catch(() => {
// noop
});
},
isNeeded() {
if (process.env.ELECTRON_RUN_AS_NODE) {
debug('Environment variable ELECTRON_RUN_AS_NODE detected, xvfb is not needed');
return false; // xvfb required for electron processes only.
}
if (os.platform() !== 'linux') {
return false;
}
if (process.env.DISPLAY) {
const issueUrl = util.getGitHubIssueUrl(4034);
const message = stripIndent`
DISPLAY environment variable is set to ${process.env.DISPLAY} on Linux
Assuming this DISPLAY points at working X11 server,
Cypress will not spawn own Xvfb
NOTE: if the X11 server is NOT working, Cypress will exit without explanation,
see ${issueUrl}
Solution: Unset the DISPLAY variable and try again:
DISPLAY= npx cypress run ...
`;
debug(message);
return false;
}
debug('undefined DISPLAY environment variable');
debug('Cypress will spawn its own Xvfb');
return true;
},
// async method, resolved with Boolean
verify() {
return xvfb.startAsync().return(true).catch(err => {
debug('Could not verify xvfb: %s', err.message);
return false;
}).finally(xvfb.stopAsync);
}
};

4
node_modules/cypress/lib/fs.js generated vendored Normal file
View File

@@ -0,0 +1,4 @@
"use strict";
const Promise = require('bluebird');
module.exports = Promise.promisifyAll(require('fs-extra'));

50
node_modules/cypress/lib/logger.js generated vendored Normal file
View File

@@ -0,0 +1,50 @@
"use strict";
const chalk = require('chalk');
let logs = [];
const logLevel = () => {
return process.env.npm_config_loglevel || 'notice';
};
const error = (...messages) => {
logs.push(messages.join(' '));
console.log(chalk.red(...messages)); // eslint-disable-line no-console
};
const warn = (...messages) => {
if (logLevel() === 'silent') return;
logs.push(messages.join(' '));
console.log(chalk.yellow(...messages)); // eslint-disable-line no-console
};
const log = (...messages) => {
if (logLevel() === 'silent' || logLevel() === 'warn') return;
logs.push(messages.join(' '));
console.log(...messages); // eslint-disable-line no-console
};
const always = (...messages) => {
logs.push(messages.join(' '));
console.log(...messages); // eslint-disable-line no-console
};
// splits long text into lines and calls log()
// on each one to allow easy unit testing for specific message
const logLines = text => {
const lines = text.split('\n');
for (const line of lines) {
log(line);
}
};
const print = () => {
return logs.join('\n');
};
const reset = () => {
logs = [];
};
module.exports = {
log,
warn,
error,
always,
logLines,
print,
reset,
logLevel
};

132
node_modules/cypress/lib/tasks/cache.js generated vendored Normal file
View File

@@ -0,0 +1,132 @@
"use strict";
const state = require('./state');
const logger = require('../logger');
const fs = require('../fs');
const util = require('../util');
const {
join
} = require('path');
const Table = require('cli-table3');
const dayjs = require('dayjs');
const relativeTime = require('dayjs/plugin/relativeTime');
const chalk = require('chalk');
const _ = require('lodash');
const getFolderSize = require('./get-folder-size');
const Bluebird = require('bluebird');
dayjs.extend(relativeTime);
// output colors for the table
const colors = {
titles: chalk.white,
dates: chalk.cyan,
values: chalk.green,
size: chalk.gray
};
const logCachePath = () => {
logger.always(state.getCacheDir());
return undefined;
};
const clear = () => {
return fs.removeAsync(state.getCacheDir());
};
const prune = () => {
const cacheDir = state.getCacheDir();
const checkedInBinaryVersion = util.pkgVersion();
let deletedBinary = false;
return fs.readdirAsync(cacheDir).then(versions => {
return Bluebird.all(versions.map(version => {
if (version !== checkedInBinaryVersion) {
deletedBinary = true;
const versionDir = join(cacheDir, version);
return fs.removeAsync(versionDir);
}
}));
}).then(() => {
if (deletedBinary) {
logger.always(`Deleted all binary caches except for the ${checkedInBinaryVersion} binary cache.`);
} else {
logger.always(`No binary caches found to prune.`);
}
}).catch({
code: 'ENOENT'
}, () => {
logger.always(`No Cypress cache was found at ${cacheDir}. Nothing to prune.`);
});
};
const fileSizeInMB = size => {
return `${(size / 1024 / 1024).toFixed(1)}MB`;
};
/**
* Collects all cached versions, finds when each was used
* and prints a table with results to the terminal
*/
const list = showSize => {
return getCachedVersions(showSize).then(binaries => {
const head = [colors.titles('version'), colors.titles('last used')];
if (showSize) {
head.push(colors.titles('size'));
}
const table = new Table({
head
});
binaries.forEach(binary => {
const versionString = colors.values(binary.version);
const lastUsed = binary.accessed ? colors.dates(binary.accessed) : 'unknown';
const row = [versionString, lastUsed];
if (showSize) {
const size = colors.size(fileSizeInMB(binary.size));
row.push(size);
}
return table.push(row);
});
logger.always(table.toString());
});
};
const getCachedVersions = showSize => {
const cacheDir = state.getCacheDir();
return fs.readdirAsync(cacheDir).filter(util.isSemver).map(version => {
return {
version,
folderPath: join(cacheDir, version)
};
}).mapSeries(binary => {
// last access time on the folder is different from last access time
// on the Cypress binary
const binaryDir = state.getBinaryDir(binary.version);
const executable = state.getPathToExecutable(binaryDir);
return fs.statAsync(executable).then(stat => {
const lastAccessedTime = _.get(stat, 'atime');
if (!lastAccessedTime) {
// the test runner has never been opened
// or could be a test simulating missing timestamp
return binary;
}
const accessed = dayjs(lastAccessedTime).fromNow();
binary.accessed = accessed;
return binary;
}, e => {
// could not find the binary or gets its stats
return binary;
});
}).mapSeries(binary => {
if (showSize) {
const binaryDir = state.getBinaryDir(binary.version);
return getFolderSize(binaryDir).then(size => {
return {
...binary,
size
};
});
}
return binary;
});
};
module.exports = {
path: logCachePath,
clear,
prune,
list,
getCachedVersions
};

319
node_modules/cypress/lib/tasks/download.js generated vendored Normal file
View File

@@ -0,0 +1,319 @@
"use strict";
const la = require('lazy-ass');
const is = require('check-more-types');
const os = require('os');
const url = require('url');
const path = require('path');
const debug = require('debug')('cypress:cli');
const request = require('@cypress/request');
const Promise = require('bluebird');
const requestProgress = require('request-progress');
const {
stripIndent
} = require('common-tags');
const getProxyForUrl = require('proxy-from-env').getProxyForUrl;
const {
throwFormErrorText,
errors
} = require('../errors');
const fs = require('../fs');
const util = require('../util');
const defaultBaseUrl = 'https://download.cypress.io/';
const defaultMaxRedirects = 10;
const getProxyForUrlWithNpmConfig = url => {
return getProxyForUrl(url) || process.env.npm_config_https_proxy || process.env.npm_config_proxy || null;
};
const getBaseUrl = () => {
if (util.getEnv('CYPRESS_DOWNLOAD_MIRROR')) {
let baseUrl = util.getEnv('CYPRESS_DOWNLOAD_MIRROR');
if (!baseUrl.endsWith('/')) {
baseUrl += '/';
}
return baseUrl;
}
return defaultBaseUrl;
};
const getCA = () => {
return new Promise(resolve => {
if (process.env.npm_config_cafile) {
fs.readFile(process.env.npm_config_cafile, 'utf8').then(cafileContent => {
resolve(cafileContent);
}).catch(() => {
resolve();
});
} else if (process.env.npm_config_ca) {
resolve(process.env.npm_config_ca);
} else {
resolve();
}
});
};
const prepend = (arch, urlPath, version) => {
const endpoint = url.resolve(getBaseUrl(), urlPath);
const platform = os.platform();
const pathTemplate = util.getEnv('CYPRESS_DOWNLOAD_PATH_TEMPLATE', true);
return pathTemplate ? pathTemplate.replace(/\\?\$\{endpoint\}/g, endpoint).replace(/\\?\$\{platform\}/g, platform).replace(/\\?\$\{arch\}/g, arch).replace(/\\?\$\{version\}/g, version) : `${endpoint}?platform=${platform}&arch=${arch}`;
};
const getUrl = (arch, version) => {
if (is.url(version)) {
debug('version is already an url', version);
return version;
}
const urlPath = version ? `desktop/${version}` : 'desktop';
return prepend(arch, urlPath, version);
};
const statusMessage = err => {
return err.statusCode ? [err.statusCode, err.statusMessage].join(' - ') : err.toString();
};
const prettyDownloadErr = (err, url) => {
const msg = stripIndent`
URL: ${url}
${statusMessage(err)}
`;
debug(msg);
return throwFormErrorText(errors.failedDownload)(msg);
};
/**
* Checks checksum and file size for the given file. Allows both
* values or just one of them to be checked.
*/
const verifyDownloadedFile = (filename, expectedSize, expectedChecksum) => {
if (expectedSize && expectedChecksum) {
debug('verifying checksum and file size');
return Promise.join(util.getFileChecksum(filename), util.getFileSize(filename), (checksum, filesize) => {
if (checksum === expectedChecksum && filesize === expectedSize) {
debug('downloaded file has the expected checksum and size ✅');
return;
}
debug('raising error: checksum or file size mismatch');
const text = stripIndent`
Corrupted download
Expected downloaded file to have checksum: ${expectedChecksum}
Computed checksum: ${checksum}
Expected downloaded file to have size: ${expectedSize}
Computed size: ${filesize}
`;
debug(text);
throw new Error(text);
});
}
if (expectedChecksum) {
debug('only checking expected file checksum %d', expectedChecksum);
return util.getFileChecksum(filename).then(checksum => {
if (checksum === expectedChecksum) {
debug('downloaded file has the expected checksum ✅');
return;
}
debug('raising error: file checksum mismatch');
const text = stripIndent`
Corrupted download
Expected downloaded file to have checksum: ${expectedChecksum}
Computed checksum: ${checksum}
`;
throw new Error(text);
});
}
if (expectedSize) {
// maybe we don't have a checksum, but at least CDN returns content length
// which we can check against the file size
debug('only checking expected file size %d', expectedSize);
return util.getFileSize(filename).then(filesize => {
if (filesize === expectedSize) {
debug('downloaded file has the expected size ✅');
return;
}
debug('raising error: file size mismatch');
const text = stripIndent`
Corrupted download
Expected downloaded file to have size: ${expectedSize}
Computed size: ${filesize}
`;
throw new Error(text);
});
}
debug('downloaded file lacks checksum or size to verify');
return Promise.resolve();
};
// downloads from given url
// return an object with
// {filename: ..., downloaded: true}
const downloadFromUrl = ({
url,
downloadDestination,
progress,
ca,
version,
redirectTTL = defaultMaxRedirects
}) => {
if (redirectTTL <= 0) {
return Promise.reject(new Error(stripIndent`
Failed downloading the Cypress binary.
There were too many redirects. The default allowance is ${defaultMaxRedirects}.
Maybe you got stuck in a redirect loop?
`));
}
return new Promise((resolve, reject) => {
const proxy = getProxyForUrlWithNpmConfig(url);
debug('Downloading package', {
url,
proxy,
downloadDestination
});
if (ca) {
debug('using custom CA details from npm config');
}
const reqOptions = {
uri: url,
...(proxy ? {
proxy
} : {}),
...(ca ? {
agentOptions: {
ca
}
} : {}),
method: 'GET',
followRedirect: false
};
const req = request(reqOptions);
// closure
let started = null;
let expectedSize;
let expectedChecksum;
requestProgress(req, {
throttle: progress.throttle
}).on('response', response => {
// we have computed checksum and filesize during test runner binary build
// and have set it on the S3 object as user meta data, available via
// these custom headers "x-amz-meta-..."
// see https://github.com/cypress-io/cypress/pull/4092
expectedSize = response.headers['x-amz-meta-size'] || response.headers['content-length'];
expectedChecksum = response.headers['x-amz-meta-checksum'];
if (expectedChecksum) {
debug('expected checksum %s', expectedChecksum);
}
if (expectedSize) {
// convert from string (all Amazon custom headers are strings)
expectedSize = Number(expectedSize);
debug('expected file size %d', expectedSize);
}
// start counting now once we've gotten
// response headers
started = new Date();
if (/^3/.test(response.statusCode)) {
const redirectVersion = response.headers['x-version'];
const redirectUrl = response.headers.location;
debug('redirect version:', redirectVersion);
debug('redirect url:', redirectUrl);
downloadFromUrl({
url: redirectUrl,
progress,
ca,
downloadDestination,
version: redirectVersion,
redirectTTL: redirectTTL - 1
}).then(resolve).catch(reject);
// if our status code does not start with 200
} else if (!/^2/.test(response.statusCode)) {
debug('response code %d', response.statusCode);
const err = new Error(stripIndent`
Failed downloading the Cypress binary.
Response code: ${response.statusCode}
Response message: ${response.statusMessage}
`);
reject(err);
// status codes here are all 2xx
} else {
// We only enable this pipe connection when we know we've got a successful return
// and handle the completion with verify and resolve
// there was a possible race condition between end of request and close of writeStream
// that is made ordered with this Promise.all
Promise.all([new Promise(r => {
return response.pipe(fs.createWriteStream(downloadDestination).on('close', r));
}), new Promise(r => response.on('end', r))]).then(() => {
debug('downloading finished');
verifyDownloadedFile(downloadDestination, expectedSize, expectedChecksum).then(() => debug('verified')).then(() => resolve(version)).catch(reject);
});
}
}).on('error', e => {
if (e.code === 'ECONNRESET') return; // sometimes proxies give ECONNRESET but we don't care
reject(e);
}).on('progress', state => {
// total time we've elapsed
// starting on our first progress notification
const elapsed = new Date() - started;
// request-progress sends a value between 0 and 1
const percentage = util.convertPercentToPercentage(state.percent);
const eta = util.calculateEta(percentage, elapsed);
// send up our percent and seconds remaining
progress.onProgress(percentage, util.secsRemaining(eta));
});
});
};
/**
* Download Cypress.zip from external versionUrl to local file.
* @param [string] version Could be "3.3.0" or full URL
* @param [string] downloadDestination Local filename to save as
*/
const start = async opts => {
let {
version,
downloadDestination,
progress,
redirectTTL
} = opts;
if (!downloadDestination) {
la(is.unemptyString(downloadDestination), 'missing download dir', opts);
}
if (!progress) {
progress = {
onProgress: () => {
return {};
}
};
}
const arch = await util.getRealArch();
const versionUrl = getUrl(arch, version);
progress.throttle = 100;
debug('needed Cypress version: %s', version);
debug('source url %s', versionUrl);
debug(`downloading cypress.zip to "${downloadDestination}"`);
// ensure download dir exists
return fs.ensureDirAsync(path.dirname(downloadDestination)).then(() => {
return getCA();
}).then(ca => {
return downloadFromUrl({
url: versionUrl,
downloadDestination,
progress,
ca,
version,
...(redirectTTL ? {
redirectTTL
} : {})
});
}).catch(err => {
return prettyDownloadErr(err, versionUrl);
});
};
module.exports = {
start,
getUrl,
getProxyForUrlWithNpmConfig,
getCA
};

33
node_modules/cypress/lib/tasks/get-folder-size.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
"use strict";
const fs = require('../fs');
const {
join
} = require('path');
const Bluebird = require('bluebird');
/**
* Get the size of a folder or a file.
*
* This function returns the actual file size of the folder (size), not the allocated space on disk (size on disk).
* For more details between the difference, check this link:
* https://www.howtogeek.com/180369/why-is-there-a-big-difference-between-size-and-size-on-disk/
*
* @param {string} path path to the file or the folder.
*/
async function getSize(path) {
const stat = await fs.lstat(path);
if (stat.isDirectory()) {
const list = await fs.readdir(path);
return Bluebird.resolve(list).reduce(async (prev, curr) => {
const currPath = join(path, curr);
const s = await fs.lstat(currPath);
if (s.isDirectory()) {
return prev + (await getSize(currPath));
}
return prev + s.size;
}, 0);
}
return stat.size;
}
module.exports = getSize;

364
node_modules/cypress/lib/tasks/install.js generated vendored Normal file
View File

@@ -0,0 +1,364 @@
"use strict";
const _ = require('lodash');
const os = require('os');
const path = require('path');
const chalk = require('chalk');
const debug = require('debug')('cypress:cli');
const {
Listr
} = require('listr2');
const Promise = require('bluebird');
const logSymbols = require('log-symbols');
const {
stripIndent
} = require('common-tags');
const fs = require('../fs');
const download = require('./download');
const util = require('../util');
const state = require('./state');
const unzip = require('./unzip');
const logger = require('../logger');
const {
throwFormErrorText,
errors
} = require('../errors');
const verbose = require('../VerboseRenderer');
const {
buildInfo,
version
} = require('../../package.json');
function _getBinaryUrlFromBuildInfo(arch, {
commitSha,
commitBranch
}) {
return `https://cdn.cypress.io/beta/binary/${version}/${os.platform()}-${arch}/${commitBranch}-${commitSha}/cypress.zip`;
}
const alreadyInstalledMsg = () => {
if (!util.isPostInstall()) {
logger.log(stripIndent`
Skipping installation:
Pass the ${chalk.yellow('--force')} option if you'd like to reinstall anyway.
`);
}
};
const displayCompletionMsg = () => {
// check here to see if we are globally installed
if (util.isInstalledGlobally()) {
// if we are display a warning
logger.log();
logger.warn(stripIndent`
${logSymbols.warning} Warning: It looks like you\'ve installed Cypress globally.
This will work, but it'\s not recommended.
The recommended way to install Cypress is as a devDependency per project.
You should probably run these commands:
- ${chalk.cyan('npm uninstall -g cypress')}
- ${chalk.cyan('npm install --save-dev cypress')}
`);
return;
}
logger.log();
logger.log('You can now open Cypress by running one of the following, depending on your package manager:');
logger.log();
logger.log(chalk.cyan('- npx cypress open'));
logger.log(chalk.cyan('- yarn cypress open'));
logger.log(chalk.cyan('- pnpm cypress open'));
logger.log();
logger.log(chalk.grey('https://on.cypress.io/opening-the-app'));
logger.log();
};
const downloadAndUnzip = ({
version,
installDir,
downloadDir
}) => {
const progress = {
throttle: 100,
onProgress: null
};
const downloadDestination = path.join(downloadDir, `cypress-${process.pid}.zip`);
const rendererOptions = getRendererOptions();
// let the user know what version of cypress we're downloading!
logger.log(`Installing Cypress ${chalk.gray(`(version: ${version})`)}`);
logger.log();
const tasks = new Listr([{
options: {
title: util.titleize('Downloading Cypress')
},
task: (ctx, task) => {
// as our download progresses indicate the status
progress.onProgress = progessify(task, 'Downloading Cypress');
return download.start({
version,
downloadDestination,
progress
}).then(redirectVersion => {
if (redirectVersion) version = redirectVersion;
debug(`finished downloading file: ${downloadDestination}`);
}).then(() => {
// save the download destination for unzipping
util.setTaskTitle(task, util.titleize(chalk.green('Downloaded Cypress')), rendererOptions.renderer);
});
}
}, unzipTask({
progress,
zipFilePath: downloadDestination,
installDir,
rendererOptions
}), {
options: {
title: util.titleize('Finishing Installation')
},
task: (ctx, task) => {
const cleanup = () => {
debug('removing zip file %s', downloadDestination);
return fs.removeAsync(downloadDestination);
};
return cleanup().then(() => {
debug('finished installation in', installDir);
util.setTaskTitle(task, util.titleize(chalk.green('Finished Installation'), chalk.gray(installDir)), rendererOptions.renderer);
});
}
}], {
rendererOptions
});
// start the tasks!
return Promise.resolve(tasks.run());
};
const validateOS = () => {
return util.getPlatformInfo().then(platformInfo => {
return platformInfo.match(/(win32-x64|linux-x64|linux-arm64|darwin-x64|darwin-arm64)/);
});
};
/**
* Returns the version to install - either a string like `1.2.3` to be fetched
* from the download server or a file path or HTTP URL.
*/
function getVersionOverride({
arch,
envVarVersion,
buildInfo
}) {
// let this environment variable reset the binary version we need
if (envVarVersion) {
return envVarVersion;
}
if (buildInfo && !buildInfo.stable) {
logger.log(chalk.yellow(stripIndent`
${logSymbols.warning} Warning: You are installing a pre-release build of Cypress.
Bugs may be present which do not exist in production builds.
This build was created from:
* Commit SHA: ${buildInfo.commitSha}
* Commit Branch: ${buildInfo.commitBranch}
* Commit Timestamp: ${buildInfo.commitDate}
`));
logger.log();
return _getBinaryUrlFromBuildInfo(arch, buildInfo);
}
}
function getEnvVarVersion() {
if (!util.getEnv('CYPRESS_INSTALL_BINARY')) return;
// because passed file paths are often double quoted
// and might have extra whitespace around, be robust and trim the string
const trimAndRemoveDoubleQuotes = true;
const envVarVersion = util.getEnv('CYPRESS_INSTALL_BINARY', trimAndRemoveDoubleQuotes);
debug('using environment variable CYPRESS_INSTALL_BINARY "%s"', envVarVersion);
return envVarVersion;
}
const start = async (options = {}) => {
debug('installing with options %j', options);
const envVarVersion = getEnvVarVersion();
if (envVarVersion === '0') {
debug('environment variable CYPRESS_INSTALL_BINARY = 0, skipping install');
logger.log(stripIndent`
${chalk.yellow('Note:')} Skipping binary installation: Environment variable CYPRESS_INSTALL_BINARY = 0.`);
logger.log();
return;
}
_.defaults(options, {
force: false,
buildInfo
});
if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
const envCache = util.getEnv('CYPRESS_CACHE_FOLDER');
logger.log(stripIndent`
${chalk.yellow('Note:')} Overriding Cypress cache directory to: ${chalk.cyan(envCache)}
Previous installs of Cypress may not be found.
`);
logger.log();
}
const pkgVersion = util.pkgVersion();
const arch = await util.getRealArch();
const versionOverride = getVersionOverride({
arch,
envVarVersion,
buildInfo: options.buildInfo
});
const versionToInstall = versionOverride || pkgVersion;
debug('version in package.json is %s, version to install is %s', pkgVersion, versionToInstall);
const installDir = state.getVersionDir(pkgVersion, options.buildInfo);
const cacheDir = state.getCacheDir();
const binaryDir = state.getBinaryDir(pkgVersion);
if (!(await validateOS())) {
return throwFormErrorText(errors.invalidOS)();
}
await fs.ensureDirAsync(cacheDir).catch({
code: 'EACCES'
}, err => {
return throwFormErrorText(errors.invalidCacheDirectory)(stripIndent`
Failed to access ${chalk.cyan(cacheDir)}:
${err.message}
`);
});
const binaryPkg = await state.getBinaryPkgAsync(binaryDir);
const binaryVersion = await state.getBinaryPkgVersion(binaryPkg);
const shouldInstall = () => {
if (!binaryVersion) {
debug('no binary installed under cli version');
return true;
}
logger.log();
logger.log(stripIndent`
Cypress ${chalk.green(binaryVersion)} is installed in ${chalk.cyan(installDir)}
`);
logger.log();
if (options.force) {
debug('performing force install over existing binary');
return true;
}
if (binaryVersion === versionToInstall || !util.isSemver(versionToInstall)) {
// our version matches, tell the user this is a noop
alreadyInstalledMsg();
return false;
}
return true;
};
// noop if we've been told not to download
if (!shouldInstall()) {
return debug('Not downloading or installing binary');
}
if (envVarVersion) {
logger.log(chalk.yellow(stripIndent`
${logSymbols.warning} Warning: Forcing a binary version different than the default.
The CLI expected to install version: ${chalk.green(pkgVersion)}
Instead we will install version: ${chalk.green(versionToInstall)}
These versions may not work properly together.
`));
logger.log();
}
const getLocalFilePath = async () => {
// see if version supplied is a path to a binary
if (await fs.pathExistsAsync(versionToInstall)) {
return path.extname(versionToInstall) === '.zip' ? versionToInstall : false;
}
const possibleFile = util.formAbsolutePath(versionToInstall);
debug('checking local file', possibleFile, 'cwd', process.cwd());
// if this exists return the path to it
// else false
if ((await fs.pathExistsAsync(possibleFile)) && path.extname(possibleFile) === '.zip') {
return possibleFile;
}
return false;
};
const pathToLocalFile = await getLocalFilePath();
if (pathToLocalFile) {
const absolutePath = path.resolve(versionToInstall);
debug('found local file at', absolutePath);
debug('skipping download');
const rendererOptions = getRendererOptions();
return new Listr([unzipTask({
progress: {
throttle: 100,
onProgress: null
},
zipFilePath: absolutePath,
installDir,
rendererOptions
})], {
rendererOptions
}).run();
}
if (options.force) {
debug('Cypress already installed at', installDir);
debug('but the installation was forced');
}
debug('preparing to download and unzip version ', versionToInstall, 'to path', installDir);
const downloadDir = os.tmpdir();
await downloadAndUnzip({
version: versionToInstall,
installDir,
downloadDir
});
// delay 1 sec for UX, unless we are testing
await Promise.delay(1000);
displayCompletionMsg();
};
module.exports = {
start,
_getBinaryUrlFromBuildInfo
};
const unzipTask = ({
zipFilePath,
installDir,
progress,
rendererOptions
}) => {
return {
options: {
title: util.titleize('Unzipping Cypress')
},
task: (ctx, task) => {
// as our unzip progresses indicate the status
progress.onProgress = progessify(task, 'Unzipping Cypress');
return unzip.start({
zipFilePath,
installDir,
progress
}).then(() => {
util.setTaskTitle(task, util.titleize(chalk.green('Unzipped Cypress')), rendererOptions.renderer);
});
}
};
};
const progessify = (task, title) => {
// return higher order function
return (percentComplete, remaining) => {
percentComplete = chalk.white(` ${percentComplete}%`);
// pluralize seconds remaining
remaining = chalk.gray(`${remaining}s`);
util.setTaskTitle(task, util.titleize(title, percentComplete, remaining), getRendererOptions().renderer);
};
};
// if we are running in CI then use
// the verbose renderer else use
// the default
const getRendererOptions = () => {
let renderer = util.isCi() ? verbose : 'default';
if (logger.logLevel() === 'silent') {
renderer = 'silent';
}
return {
renderer
};
};

185
node_modules/cypress/lib/tasks/state.js generated vendored Normal file
View File

@@ -0,0 +1,185 @@
"use strict";
const _ = require('lodash');
const os = require('os');
const path = require('path');
const untildify = require('untildify');
const debug = require('debug')('cypress:cli');
const fs = require('../fs');
const util = require('../util');
const getPlatformExecutable = () => {
const platform = os.platform();
switch (platform) {
case 'darwin':
return 'Contents/MacOS/Cypress';
case 'linux':
return 'Cypress';
case 'win32':
return 'Cypress.exe';
// TODO handle this error using our standard
default:
throw new Error(`Platform: "${platform}" is not supported.`);
}
};
const getPlatFormBinaryFolder = () => {
const platform = os.platform();
switch (platform) {
case 'darwin':
return 'Cypress.app';
case 'linux':
return 'Cypress';
case 'win32':
return 'Cypress';
// TODO handle this error using our standard
default:
throw new Error(`Platform: "${platform}" is not supported.`);
}
};
const getBinaryPkgPath = binaryDir => {
const platform = os.platform();
switch (platform) {
case 'darwin':
return path.join(binaryDir, 'Contents', 'Resources', 'app', 'package.json');
case 'linux':
return path.join(binaryDir, 'resources', 'app', 'package.json');
case 'win32':
return path.join(binaryDir, 'resources', 'app', 'package.json');
// TODO handle this error using our standard
default:
throw new Error(`Platform: "${platform}" is not supported.`);
}
};
/**
* Get path to binary directory
*/
const getBinaryDir = (version = util.pkgVersion()) => {
return path.join(getVersionDir(version), getPlatFormBinaryFolder());
};
const getVersionDir = (version = util.pkgVersion(), buildInfo = util.pkgBuildInfo()) => {
if (buildInfo && !buildInfo.stable) {
version = ['beta', version, buildInfo.commitBranch, buildInfo.commitSha.slice(0, 8)].join('-');
}
return path.join(getCacheDir(), version);
};
/**
* When executing "npm postinstall" hook, the working directory is set to
* "<current folder>/node_modules/cypress", which can be surprising when using relative paths.
*/
const isInstallingFromPostinstallHook = () => {
// individual folders
const cwdFolders = process.cwd().split(path.sep);
const length = cwdFolders.length;
return cwdFolders[length - 2] === 'node_modules' && cwdFolders[length - 1] === 'cypress';
};
const getCacheDir = () => {
let cache_directory = util.getCacheDir();
if (util.getEnv('CYPRESS_CACHE_FOLDER')) {
const envVarCacheDir = untildify(util.getEnv('CYPRESS_CACHE_FOLDER'));
debug('using environment variable CYPRESS_CACHE_FOLDER %s', envVarCacheDir);
if (!path.isAbsolute(envVarCacheDir) && isInstallingFromPostinstallHook()) {
const packageRootFolder = path.join('..', '..', envVarCacheDir);
cache_directory = path.resolve(packageRootFolder);
debug('installing from postinstall hook, original root folder is %s', packageRootFolder);
debug('and resolved cache directory is %s', cache_directory);
} else {
cache_directory = path.resolve(envVarCacheDir);
}
}
return cache_directory;
};
const parseRealPlatformBinaryFolderAsync = binaryPath => {
return fs.realpathAsync(binaryPath).then(realPath => {
debug('CYPRESS_RUN_BINARY has realpath:', realPath);
if (!realPath.toString().endsWith(getPlatformExecutable())) {
return false;
}
if (os.platform() === 'darwin') {
return path.resolve(realPath, '..', '..', '..');
}
return path.resolve(realPath, '..');
});
};
const getDistDir = () => {
return path.join(__dirname, '..', '..', 'dist');
};
/**
* Returns full filename to the file that keeps the Test Runner verification state as JSON text.
* Note: the binary state file will be stored one level up from the given binary folder.
* @param {string} binaryDir - full path to the folder holding the binary.
*/
const getBinaryStatePath = binaryDir => {
return path.join(binaryDir, '..', 'binary_state.json');
};
const getBinaryStateContentsAsync = binaryDir => {
const fullPath = getBinaryStatePath(binaryDir);
return fs.readJsonAsync(fullPath).catch({
code: 'ENOENT'
}, SyntaxError, () => {
debug('could not read binary_state.json file at "%s"', fullPath);
return {};
});
};
const getBinaryVerifiedAsync = binaryDir => {
return getBinaryStateContentsAsync(binaryDir).tap(debug).get('verified');
};
const clearBinaryStateAsync = binaryDir => {
return fs.removeAsync(getBinaryStatePath(binaryDir));
};
/**
* Writes the new binary status.
* @param {boolean} verified The new test runner state after smoke test
* @param {string} binaryDir Folder holding the binary
* @returns {Promise<void>} returns a promise
*/
const writeBinaryVerifiedAsync = (verified, binaryDir) => {
return getBinaryStateContentsAsync(binaryDir).then(contents => {
return fs.outputJsonAsync(getBinaryStatePath(binaryDir), _.extend(contents, {
verified
}), {
spaces: 2
});
});
};
const getPathToExecutable = binaryDir => {
return path.join(binaryDir, getPlatformExecutable());
};
/**
* Resolves with an object read from the binary app package.json file.
* If the file does not exist resolves with null
*/
const getBinaryPkgAsync = binaryDir => {
const pathToPackageJson = getBinaryPkgPath(binaryDir);
debug('Reading binary package.json from:', pathToPackageJson);
return fs.pathExistsAsync(pathToPackageJson).then(exists => {
if (!exists) {
return null;
}
return fs.readJsonAsync(pathToPackageJson);
});
};
const getBinaryPkgVersion = o => _.get(o, 'version', null);
const getBinaryElectronVersion = o => _.get(o, 'electronVersion', null);
const getBinaryElectronNodeVersion = o => _.get(o, 'electronNodeVersion', null);
module.exports = {
getPathToExecutable,
getPlatformExecutable,
// those names start to sound like Java
getBinaryElectronNodeVersion,
getBinaryElectronVersion,
getBinaryPkgVersion,
getBinaryVerifiedAsync,
getBinaryPkgAsync,
getBinaryPkgPath,
getBinaryDir,
getCacheDir,
clearBinaryStateAsync,
writeBinaryVerifiedAsync,
parseRealPlatformBinaryFolderAsync,
getDistDir,
getVersionDir
};

200
node_modules/cypress/lib/tasks/unzip.js generated vendored Normal file
View File

@@ -0,0 +1,200 @@
"use strict";
const _ = require('lodash');
const la = require('lazy-ass');
const is = require('check-more-types');
const cp = require('child_process');
const os = require('os');
const yauzl = require('yauzl');
const debug = require('debug')('cypress:cli:unzip');
const extract = require('extract-zip');
const Promise = require('bluebird');
const readline = require('readline');
const {
throwFormErrorText,
errors
} = require('../errors');
const fs = require('../fs');
const util = require('../util');
const unzipTools = {
extract
};
// expose this function for simple testing
const unzip = ({
zipFilePath,
installDir,
progress
}) => {
debug('unzipping from %s', zipFilePath);
debug('into', installDir);
if (!zipFilePath) {
throw new Error('Missing zip filename');
}
const startTime = Date.now();
let yauzlDoneTime = 0;
return fs.ensureDirAsync(installDir).then(() => {
return new Promise((resolve, reject) => {
return yauzl.open(zipFilePath, (err, zipFile) => {
yauzlDoneTime = Date.now();
if (err) {
debug('error using yauzl %s', err.message);
return reject(err);
}
const total = zipFile.entryCount;
debug('zipFile entries count', total);
const started = new Date();
let percent = 0;
let count = 0;
const notify = percent => {
const elapsed = +new Date() - +started;
const eta = util.calculateEta(percent, elapsed);
progress.onProgress(percent, util.secsRemaining(eta));
};
const tick = () => {
count += 1;
percent = count / total * 100;
const displayPercent = percent.toFixed(0);
return notify(displayPercent);
};
const unzipWithNode = () => {
debug('unzipping with node.js (slow)');
const opts = {
dir: installDir,
onEntry: tick
};
debug('calling Node extract tool %s %o', zipFilePath, opts);
return unzipTools.extract(zipFilePath, opts).then(() => {
debug('node unzip finished');
return resolve();
}).catch(err => {
const error = err || new Error('Unknown error with Node extract tool');
debug('error %s', error.message);
return reject(error);
});
};
const unzipFallback = _.once(unzipWithNode);
const unzipWithUnzipTool = () => {
debug('unzipping via `unzip`');
const inflatingRe = /inflating:/;
const sp = cp.spawn('unzip', ['-o', zipFilePath, '-d', installDir]);
sp.on('error', err => {
debug('unzip tool error: %s', err.message);
unzipFallback();
});
sp.on('close', code => {
debug('unzip tool close with code %d', code);
if (code === 0) {
percent = 100;
notify(percent);
return resolve();
}
debug('`unzip` failed %o', {
code
});
return unzipFallback();
});
sp.stdout.on('data', data => {
if (inflatingRe.test(data)) {
return tick();
}
});
sp.stderr.on('data', data => {
debug('`unzip` stderr %s', data);
});
};
// we attempt to first unzip with the native osx
// ditto because its less likely to have problems
// with corruption, symlinks, or icons causing failures
// and can handle resource forks
// http://automatica.com.au/2011/02/unzip-mac-os-x-zip-in-terminal/
const unzipWithOsx = () => {
debug('unzipping via `ditto`');
const copyingFileRe = /^copying file/;
const sp = cp.spawn('ditto', ['-xkV', zipFilePath, installDir]);
// f-it just unzip with node
sp.on('error', err => {
debug(err.message);
unzipFallback();
});
sp.on('close', code => {
if (code === 0) {
// make sure we get to 100% on the progress bar
// because reading in lines is not really accurate
percent = 100;
notify(percent);
return resolve();
}
debug('`ditto` failed %o', {
code
});
return unzipFallback();
});
return readline.createInterface({
input: sp.stderr
}).on('line', line => {
if (copyingFileRe.test(line)) {
return tick();
}
});
};
switch (os.platform()) {
case 'darwin':
return unzipWithOsx();
case 'linux':
return unzipWithUnzipTool();
case 'win32':
return unzipWithNode();
default:
return;
}
});
}).tap(() => {
debug('unzip completed %o', {
yauzlMs: yauzlDoneTime - startTime,
unzipMs: Date.now() - yauzlDoneTime
});
});
});
};
function isMaybeWindowsMaxPathLengthError(err) {
return os.platform() === 'win32' && err.code === 'ENOENT' && err.syscall === 'realpath';
}
const start = async ({
zipFilePath,
installDir,
progress
}) => {
la(is.unemptyString(installDir), 'missing installDir');
if (!progress) {
progress = {
onProgress: () => {
return {};
}
};
}
try {
const installDirExists = await fs.pathExists(installDir);
if (installDirExists) {
debug('removing existing unzipped binary', installDir);
await fs.removeAsync(installDir);
}
await unzip({
zipFilePath,
installDir,
progress
});
} catch (err) {
const errorTemplate = isMaybeWindowsMaxPathLengthError(err) ? errors.failedUnzipWindowsMaxPathLength : errors.failedUnzip;
await throwFormErrorText(errorTemplate)(err);
}
};
module.exports = {
start,
utils: {
unzip,
unzipTools
}
};

300
node_modules/cypress/lib/tasks/verify.js generated vendored Normal file
View File

@@ -0,0 +1,300 @@
"use strict";
const _ = require('lodash');
const chalk = require('chalk');
const {
Listr
} = require('listr2');
const debug = require('debug')('cypress:cli');
const {
stripIndent
} = require('common-tags');
const Promise = require('bluebird');
const logSymbols = require('log-symbols');
const path = require('path');
const os = require('os');
const verbose = require('../VerboseRenderer');
const {
throwFormErrorText,
errors
} = require('../errors');
const util = require('../util');
const logger = require('../logger');
const xvfb = require('../exec/xvfb');
const state = require('./state');
const VERIFY_TEST_RUNNER_TIMEOUT_MS = +util.getEnv('CYPRESS_VERIFY_TIMEOUT') || 30000;
const checkExecutable = binaryDir => {
const executable = state.getPathToExecutable(binaryDir);
debug('checking if executable exists', executable);
return util.isExecutableAsync(executable).then(isExecutable => {
debug('Binary is executable? :', isExecutable);
if (!isExecutable) {
return throwFormErrorText(errors.binaryNotExecutable(executable))();
}
}).catch({
code: 'ENOENT'
}, () => {
if (util.isCi()) {
return throwFormErrorText(errors.notInstalledCI(executable))();
}
return throwFormErrorText(errors.missingApp(binaryDir))(stripIndent`
Cypress executable not found at: ${chalk.cyan(executable)}
`);
});
};
const runSmokeTest = (binaryDir, options) => {
let executable = state.getPathToExecutable(binaryDir);
const onSmokeTestError = (smokeTestCommand, linuxWithDisplayEnv) => {
return err => {
debug('Smoke test failed:', err);
let errMessage = err.stderr || err.message;
debug('error message:', errMessage);
if (err.timedOut) {
debug('error timedOut is true');
return throwFormErrorText(errors.smokeTestFailure(smokeTestCommand, true))(errMessage);
}
if (linuxWithDisplayEnv && util.isBrokenGtkDisplay(errMessage)) {
util.logBrokenGtkDisplayWarning();
return throwFormErrorText(errors.invalidSmokeTestDisplayError)(errMessage);
}
return throwFormErrorText(errors.missingDependency)(errMessage);
};
};
const needsXvfb = xvfb.isNeeded();
debug('needs Xvfb?', needsXvfb);
/**
* Spawn Cypress running smoke test to check if all operating system
* dependencies are good.
*/
const spawn = linuxWithDisplayEnv => {
const random = _.random(0, 1000);
const args = ['--smoke-test', `--ping=${random}`];
if (needsSandbox()) {
// electron requires --no-sandbox to run as root
debug('disabling Electron sandbox');
args.unshift('--no-sandbox');
}
if (options.dev) {
executable = 'node';
args.unshift(path.resolve(__dirname, '..', '..', '..', 'scripts', 'start.js'));
}
const smokeTestCommand = `${executable} ${args.join(' ')}`;
debug('running smoke test');
debug('using Cypress executable %s', executable);
debug('smoke test command:', smokeTestCommand);
debug('smoke test timeout %d ms', options.smokeTestTimeout);
const stdioOptions = _.extend({}, {
env: {
...process.env,
FORCE_COLOR: 0
},
timeout: options.smokeTestTimeout
});
return Promise.resolve(util.exec(executable, args, stdioOptions)).catch(onSmokeTestError(smokeTestCommand, linuxWithDisplayEnv)).then(result => {
// TODO: when execa > 1.1 is released
// change this to `result.all` for both stderr and stdout
// use lodash to be robust during tests against null result or missing stdout
const smokeTestStdout = _.get(result, 'stdout', '');
debug('smoke test stdout "%s"', smokeTestStdout);
if (!util.stdoutLineMatches(String(random), smokeTestStdout)) {
debug('Smoke test failed because could not find %d in:', random, result);
const smokeTestStderr = _.get(result, 'stderr', '');
const errorText = smokeTestStderr || smokeTestStdout;
return throwFormErrorText(errors.smokeTestFailure(smokeTestCommand, false))(errorText);
}
});
};
const spawnInXvfb = linuxWithDisplayEnv => {
return xvfb.start().then(() => {
return spawn(linuxWithDisplayEnv);
}).finally(xvfb.stop);
};
const userFriendlySpawn = linuxWithDisplayEnv => {
debug('spawning, should retry on display problem?', Boolean(linuxWithDisplayEnv));
return spawn(linuxWithDisplayEnv).catch({
code: 'INVALID_SMOKE_TEST_DISPLAY_ERROR'
}, () => {
return spawnInXvfb(linuxWithDisplayEnv);
});
};
if (needsXvfb) {
return spawnInXvfb();
}
// if we are on linux and there's already a DISPLAY
// set, then we may need to rerun cypress after
// spawning our own Xvfb server
const linuxWithDisplayEnv = util.isPossibleLinuxWithIncorrectDisplay();
return userFriendlySpawn(linuxWithDisplayEnv);
};
function testBinary(version, binaryDir, options) {
debug('running binary verification check', version);
// if running from 'cypress verify', don't print this message
if (!options.force) {
logger.log(stripIndent`
It looks like this is your first time using Cypress: ${chalk.cyan(version)}
`);
}
logger.log();
// if we are running in CI then use
// the verbose renderer else use
// the default
let renderer = util.isCi() ? verbose : 'default';
if (logger.logLevel() === 'silent') renderer = 'silent';
const rendererOptions = {
renderer
};
const tasks = new Listr([{
options: {
title: util.titleize('Verifying Cypress can run', chalk.gray(binaryDir))
},
task: (ctx, task) => {
debug('clearing out the verified version');
return state.clearBinaryStateAsync(binaryDir).then(() => {
return Promise.all([runSmokeTest(binaryDir, options), Promise.resolve().delay(1500) // good user experience
]);
}).then(() => {
debug('write verified: true');
return state.writeBinaryVerifiedAsync(true, binaryDir);
}).then(() => {
util.setTaskTitle(task, util.titleize(chalk.green('Verified Cypress!'), chalk.gray(binaryDir)), rendererOptions.renderer);
});
}
}], {
rendererOptions
});
return tasks.run();
}
const maybeVerify = (installedVersion, binaryDir, options) => {
return state.getBinaryVerifiedAsync(binaryDir).then(isVerified => {
debug('is Verified ?', isVerified);
let shouldVerify = !isVerified;
// force verify if options.force
if (options.force) {
debug('force verify');
shouldVerify = true;
}
if (shouldVerify) {
return testBinary(installedVersion, binaryDir, options).then(() => {
if (options.welcomeMessage) {
logger.log();
logger.log('Opening Cypress...');
}
});
}
});
};
const start = (options = {}) => {
debug('verifying Cypress app');
const packageVersion = util.pkgVersion();
let binaryDir = state.getBinaryDir(packageVersion);
_.defaults(options, {
dev: false,
force: false,
welcomeMessage: true,
smokeTestTimeout: VERIFY_TEST_RUNNER_TIMEOUT_MS,
skipVerify: util.getEnv('CYPRESS_SKIP_VERIFY') === 'true'
});
if (options.skipVerify) {
debug('skipping verification of the Cypress app');
return Promise.resolve();
}
if (options.dev) {
return runSmokeTest('', options);
}
const parseBinaryEnvVar = () => {
const envBinaryPath = util.getEnv('CYPRESS_RUN_BINARY');
debug('CYPRESS_RUN_BINARY exists, =', envBinaryPath);
logger.log(stripIndent`
${chalk.yellow('Note:')} You have set the environment variable:
${chalk.white('CYPRESS_RUN_BINARY=')}${chalk.cyan(envBinaryPath)}
This overrides the default Cypress binary path used.
`);
logger.log();
return util.isExecutableAsync(envBinaryPath).then(isExecutable => {
debug('CYPRESS_RUN_BINARY is executable? :', isExecutable);
if (!isExecutable) {
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(stripIndent`
The supplied binary path is not executable
`);
}
}).then(() => {
return state.parseRealPlatformBinaryFolderAsync(envBinaryPath);
}).then(envBinaryDir => {
if (!envBinaryDir) {
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))();
}
debug('CYPRESS_RUN_BINARY has binaryDir:', envBinaryDir);
binaryDir = envBinaryDir;
}).catch({
code: 'ENOENT'
}, err => {
return throwFormErrorText(errors.CYPRESS_RUN_BINARY.notValid(envBinaryPath))(err.message);
});
};
return Promise.try(() => {
debug('checking environment variables');
if (util.getEnv('CYPRESS_RUN_BINARY')) {
return parseBinaryEnvVar();
}
}).then(() => {
return checkExecutable(binaryDir);
}).tap(() => {
return debug('binaryDir is ', binaryDir);
}).then(() => {
return state.getBinaryPkgAsync(binaryDir);
}).then(pkg => {
return state.getBinaryPkgVersion(pkg);
}).then(binaryVersion => {
if (!binaryVersion) {
debug('no Cypress binary found for cli version ', packageVersion);
return throwFormErrorText(errors.missingApp(binaryDir))(`
Cannot read binary version from: ${chalk.cyan(state.getBinaryPkgPath(binaryDir))}
`);
}
debug(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`);
if (binaryVersion !== packageVersion) {
// warn if we installed with CYPRESS_INSTALL_BINARY or changed version
// in the package.json
logger.log(`Found binary version ${chalk.green(binaryVersion)} installed in: ${chalk.cyan(binaryDir)}`);
logger.log();
logger.warn(stripIndent`
${logSymbols.warning} Warning: Binary version ${chalk.green(binaryVersion)} does not match the expected package version ${chalk.green(packageVersion)}
These versions may not work properly together.
`);
logger.log();
}
return maybeVerify(binaryVersion, binaryDir, options);
}).catch(err => {
if (err.known) {
throw err;
}
return throwFormErrorText(errors.unexpected)(err.stack);
});
};
const isLinuxLike = () => os.platform() !== 'win32';
/**
* Returns true if running on a system where Electron needs "--no-sandbox" flag.
* @see https://crbug.com/638180
*
* On Debian we had problems running in sandbox even for non-root users.
* @see https://github.com/cypress-io/cypress/issues/5434
* Seems there is a lot of discussion around this issue among Electron users
* @see https://github.com/electron/electron/issues/17972
*/
const needsSandbox = () => isLinuxLike();
module.exports = {
start,
VERIFY_TEST_RUNNER_TIMEOUT_MS,
needsSandbox
};

460
node_modules/cypress/lib/util.js generated vendored Normal file
View File

@@ -0,0 +1,460 @@
"use strict";
const _ = require('lodash');
const arch = require('arch');
const os = require('os');
const ospath = require('ospath');
const crypto = require('crypto');
const la = require('lazy-ass');
const is = require('check-more-types');
const tty = require('tty');
const path = require('path');
const isCi = require('is-ci');
const execa = require('execa');
const getos = require('getos');
const chalk = require('chalk');
const Promise = require('bluebird');
const cachedir = require('cachedir');
const logSymbols = require('log-symbols');
const executable = require('executable');
const {
stripIndent
} = require('common-tags');
const supportsColor = require('supports-color');
const isInstalledGlobally = require('is-installed-globally');
const logger = require('./logger');
const debug = require('debug')('cypress:cli');
const fs = require('./fs');
const pkg = require(path.join(__dirname, '..', 'package.json'));
const issuesUrl = 'https://github.com/cypress-io/cypress/issues';
const getosAsync = Promise.promisify(getos);
/**
* Returns SHA512 of a file
*
* Implementation lifted from https://github.com/sindresorhus/hasha
* but without bringing that dependency (since hasha is Node v8+)
*/
const getFileChecksum = filename => {
la(is.unemptyString(filename), 'expected filename', filename);
const hashStream = () => {
const s = crypto.createHash('sha512');
s.setEncoding('hex');
return s;
};
return new Promise((resolve, reject) => {
const stream = fs.createReadStream(filename);
stream.on('error', reject).pipe(hashStream()).on('error', reject).on('finish', function () {
resolve(this.read());
});
});
};
const getFileSize = filename => {
la(is.unemptyString(filename), 'expected filename', filename);
return fs.statAsync(filename).get('size');
};
const isBrokenGtkDisplayRe = /Gtk: cannot open display/;
const stringify = val => {
return _.isObject(val) ? JSON.stringify(val) : val;
};
function normalizeModuleOptions(options = {}) {
return _.mapValues(options, stringify);
}
/**
* Returns true if the platform is Linux. We do a lot of different
* stuff on Linux (like Xvfb) and it helps to has readable code
*/
const isLinux = () => {
return os.platform() === 'linux';
};
/**
* If the DISPLAY variable is set incorrectly, when trying to spawn
* Cypress executable we get an error like this:
```
[1005:0509/184205.663837:WARNING:browser_main_loop.cc(258)] Gtk: cannot open display: 99
```
*/
const isBrokenGtkDisplay = str => {
return isBrokenGtkDisplayRe.test(str);
};
const isPossibleLinuxWithIncorrectDisplay = () => {
return isLinux() && process.env.DISPLAY;
};
const logBrokenGtkDisplayWarning = () => {
debug('Cypress exited due to a broken gtk display because of a potential invalid DISPLAY env... retrying after starting Xvfb');
// if we get this error, we are on Linux and DISPLAY is set
logger.warn(stripIndent`
${logSymbols.warning} Warning: Cypress failed to start.
This is likely due to a misconfigured DISPLAY environment variable.
DISPLAY was set to: "${process.env.DISPLAY}"
Cypress will attempt to fix the problem and rerun.
`);
logger.warn();
};
function stdoutLineMatches(expectedLine, stdout) {
const lines = stdout.split('\n').map(val => val.trim());
return lines.some(line => line === expectedLine);
}
/**
* Confirms if given value is a valid CYPRESS_INTERNAL_ENV value. Undefined values
* are valid, because the system can set the default one.
*
* @param {string} value
* @example util.isValidCypressInternalEnvValue(process.env.CYPRESS_INTERNAL_ENV)
*/
function isValidCypressInternalEnvValue(value) {
if (_.isUndefined(value)) {
// will get default value
return true;
}
// names of config environments, see "packages/server/config/app.json"
const names = ['development', 'test', 'staging', 'production'];
return _.includes(names, value);
}
/**
* Confirms if given value is a non-production CYPRESS_INTERNAL_ENV value.
* Undefined values are valid, because the system can set the default one.
*
* @param {string} value
* @example util.isNonProductionCypressInternalEnvValue(process.env.CYPRESS_INTERNAL_ENV)
*/
function isNonProductionCypressInternalEnvValue(value) {
return !_.isUndefined(value) && value !== 'production';
}
/**
* Prints NODE_OPTIONS using debug() module, but only
* if DEBUG=cypress... is set
*/
function printNodeOptions(log = debug) {
if (!log.enabled) {
return;
}
if (process.env.NODE_OPTIONS) {
log('NODE_OPTIONS=%s', process.env.NODE_OPTIONS);
} else {
log('NODE_OPTIONS is not set');
}
}
/**
* Removes double quote characters
* from the start and end of the given string IF they are both present
*
* @param {string} str Input string
* @returns {string} Trimmed string or the original string if there are no double quotes around it.
* @example
```
dequote('"foo"')
// returns string 'foo'
dequote('foo')
// returns string 'foo'
```
*/
const dequote = str => {
la(is.string(str), 'expected a string to remove double quotes', str);
if (str.length > 1 && str[0] === '"' && str[str.length - 1] === '"') {
return str.substr(1, str.length - 2);
}
return str;
};
const parseOpts = opts => {
opts = _.pick(opts, 'autoCancelAfterFailures', 'browser', 'cachePath', 'cacheList', 'cacheClear', 'cachePrune', 'ciBuildId', 'ct', 'component', 'config', 'configFile', 'cypressVersion', 'destination', 'detached', 'dev', 'e2e', 'exit', 'env', 'force', 'global', 'group', 'headed', 'headless', 'inspect', 'inspectBrk', 'key', 'path', 'parallel', 'port', 'project', 'quiet', 'reporter', 'reporterOptions', 'record', 'runnerUi', 'runProject', 'spec', 'tag');
if (opts.exit) {
opts = _.omit(opts, 'exit');
}
// some options might be quoted - which leads to unexpected results
// remove double quotes from certain options
const cleanOpts = {
...opts
};
const toDequote = ['group', 'ciBuildId'];
for (const prop of toDequote) {
if (_.has(opts, prop)) {
cleanOpts[prop] = dequote(opts[prop]);
}
}
debug('parsed cli options %o', cleanOpts);
return cleanOpts;
};
/**
* Copy of packages/server/lib/browsers/utils.ts
* because we need same functionality in CLI to show the path :(
*/
const getApplicationDataFolder = (...paths) => {
const {
env
} = process;
// allow overriding the app_data folder
let folder = env.CYPRESS_CONFIG_ENV || env.CYPRESS_INTERNAL_ENV || 'development';
const PRODUCT_NAME = pkg.productName || pkg.name;
const OS_DATA_PATH = ospath.data();
const ELECTRON_APP_DATA_PATH = path.join(OS_DATA_PATH, PRODUCT_NAME);
if (process.env.CYPRESS_INTERNAL_E2E_TESTING_SELF) {
folder = `${folder}-e2e-test`;
}
const p = path.join(ELECTRON_APP_DATA_PATH, 'cy', folder, ...paths);
return p;
};
const util = {
normalizeModuleOptions,
parseOpts,
isValidCypressInternalEnvValue,
isNonProductionCypressInternalEnvValue,
printNodeOptions,
isCi() {
return isCi;
},
getEnvOverrides(options = {}) {
return _.chain({}).extend(util.getEnvColors()).extend(util.getForceTty()).omitBy(_.isUndefined) // remove undefined values
.mapValues(value => {
// stringify to 1 or 0
return value ? '1' : '0';
}).extend(util.getOriginalNodeOptions()).value();
},
getOriginalNodeOptions() {
const opts = {};
if (process.env.NODE_OPTIONS) {
opts.ORIGINAL_NODE_OPTIONS = process.env.NODE_OPTIONS;
}
return opts;
},
getForceTty() {
return {
FORCE_STDIN_TTY: util.isTty(process.stdin.fd),
FORCE_STDOUT_TTY: util.isTty(process.stdout.fd),
FORCE_STDERR_TTY: util.isTty(process.stderr.fd)
};
},
getEnvColors() {
const sc = util.supportsColor();
return {
FORCE_COLOR: sc,
DEBUG_COLORS: sc,
MOCHA_COLORS: sc ? true : undefined
};
},
isTty(fd) {
return tty.isatty(fd);
},
supportsColor() {
// if we've been explicitly told not to support
// color then turn this off
if (process.env.NO_COLOR) {
return false;
}
// https://github.com/cypress-io/cypress/issues/1747
// always return true in CI providers
if (process.env.CI) {
return true;
}
// ensure that both stdout and stderr support color
return Boolean(supportsColor.stdout) && Boolean(supportsColor.stderr);
},
cwd() {
return process.cwd();
},
pkgBuildInfo() {
return pkg.buildInfo;
},
pkgVersion() {
return pkg.version;
},
exit(code) {
process.exit(code);
},
logErrorExit1(err) {
logger.error(err.message);
process.exit(1);
},
dequote,
titleize(...args) {
// prepend first arg with space
// and pad so that all messages line up
args[0] = _.padEnd(` ${args[0]}`, 24);
// get rid of any falsy values
args = _.compact(args);
return chalk.blue(...args);
},
calculateEta(percent, elapsed) {
// returns the number of seconds remaining
// if we're at 100% already just return 0
if (percent === 100) {
return 0;
}
// take the percentage and divide by one
// and multiple that against elapsed
// subtracting what's already elapsed
return elapsed * (1 / (percent / 100)) - elapsed;
},
convertPercentToPercentage(num) {
// convert a percent with values between 0 and 1
// with decimals, so that it is between 0 and 100
// and has no decimal places
return Math.round(_.isFinite(num) ? num * 100 : 0);
},
secsRemaining(eta) {
// calculate the seconds reminaing with no decimal places
return (_.isFinite(eta) ? eta / 1000 : 0).toFixed(0);
},
setTaskTitle(task, title, renderer) {
// only update the renderer title when not running in CI
if (renderer === 'default' && task.title !== title) {
task.title = title;
}
},
isInstalledGlobally() {
return isInstalledGlobally;
},
isSemver(str) {
return /^(\d+\.)?(\d+\.)?(\*|\d+)$/.test(str);
},
isExecutableAsync(filePath) {
return Promise.resolve(executable(filePath));
},
isLinux,
getOsVersionAsync() {
return Promise.try(() => {
if (isLinux()) {
return getosAsync().then(osInfo => {
return [osInfo.dist, osInfo.release].join(' - ');
}).catch(() => {
return os.release();
});
}
return os.release();
});
},
async getPlatformInfo() {
const [version, osArch] = await Promise.all([util.getOsVersionAsync(), this.getRealArch()]);
return stripIndent`
Platform: ${os.platform()}-${osArch} (${version})
Cypress Version: ${util.pkgVersion()}
`;
},
_cachedArch: undefined,
/**
* Attempt to return the real system arch (not process.arch, which is only the Node binary's arch)
*/
async getRealArch() {
if (this._cachedArch) return this._cachedArch;
async function _getRealArch() {
const osPlatform = os.platform();
// eslint-disable-next-line no-restricted-syntax
const osArch = os.arch();
debug('detecting arch %o', {
osPlatform,
osArch
});
if (osArch === 'arm64') return 'arm64';
if (osPlatform === 'darwin') {
// could possibly be x64 node on arm64 darwin, check if we are being translated by Rosetta
// https://stackoverflow.com/a/65347893/3474615
const {
stdout
} = await execa('sysctl', ['-n', 'sysctl.proc_translated']).catch(() => '');
debug('rosetta check result: %o', {
stdout
});
if (stdout === '1') return 'arm64';
}
if (osPlatform === 'linux') {
// could possibly be x64 node on arm64 linux, check the "machine hardware name"
// list of names for reference: https://stackoverflow.com/a/45125525/3474615
const {
stdout
} = await execa('uname', ['-m']).catch(() => '');
debug('arm uname -m result: %o ', {
stdout
});
if (['aarch64_be', 'aarch64', 'armv8b', 'armv8l'].includes(stdout)) return 'arm64';
}
// eslint-disable-next-line no-restricted-syntax
const pkgArch = arch();
if (pkgArch === 'x86') return 'ia32';
return pkgArch;
}
return this._cachedArch = await _getRealArch();
},
// attention:
// when passing relative path to NPM post install hook, the current working
// directory is set to the `node_modules/cypress` folder
// the user is probably passing relative path with respect to root package folder
formAbsolutePath(filename) {
if (path.isAbsolute(filename)) {
return filename;
}
return path.join(process.cwd(), '..', '..', filename);
},
getEnv(varName, trim) {
la(is.unemptyString(varName), 'expected environment variable name, not', varName);
const configVarName = `npm_config_${varName}`;
const configVarNameLower = configVarName.toLowerCase();
const packageConfigVarName = `npm_package_config_${varName}`;
let result;
if (process.env.hasOwnProperty(varName)) {
debug(`Using ${varName} from environment variable`);
result = process.env[varName];
} else if (process.env.hasOwnProperty(configVarName)) {
debug(`Using ${varName} from npm config`);
result = process.env[configVarName];
} else if (process.env.hasOwnProperty(configVarNameLower)) {
debug(`Using ${varName.toLowerCase()} from npm config`);
result = process.env[configVarNameLower];
} else if (process.env.hasOwnProperty(packageConfigVarName)) {
debug(`Using ${varName} from package.json config`);
result = process.env[packageConfigVarName];
}
// environment variables are often set double quotes to escape characters
// and on Windows it can lead to weird things: for example
// set FOO="C:\foo.txt" && node -e "console.log('>>>%s<<<', process.env.FOO)"
// will print
// >>>"C:\foo.txt" <<<
// see https://github.com/cypress-io/cypress/issues/4506#issuecomment-506029942
// so for sanity sake we should first trim whitespace characters and remove
// double quotes around environment strings if the caller is expected to
// use this environment string as a file path
return trim ? dequote(_.trim(result)) : result;
},
getCacheDir() {
return cachedir('Cypress');
},
isPostInstall() {
return process.env.npm_lifecycle_event === 'postinstall';
},
exec: execa,
stdoutLineMatches,
issuesUrl,
isBrokenGtkDisplay,
logBrokenGtkDisplayWarning,
isPossibleLinuxWithIncorrectDisplay,
getGitHubIssueUrl(number) {
la(is.positive(number), 'github issue should be a positive number', number);
la(_.isInteger(number), 'github issue should be an integer', number);
return `${issuesUrl}/${number}`;
},
getFileChecksum,
getFileSize,
getApplicationDataFolder
};
module.exports = util;

140
node_modules/cypress/mount-utils/README.md generated vendored Normal file
View File

@@ -0,0 +1,140 @@
# @cypress/mount-utils
> **Note** this package is not meant to be used outside of cypress component testing.
This library exports some shared types and utility functions designed to build adapters for components frameworks.
It is used in:
- [`@cypress/react`](https://github.com/cypress-io/cypress/tree/develop/npm/react)
- [`@cypress/vue`](https://github.com/cypress-io/cypress/tree/develop/npm/vue)
- [`@cypress/svelte`](https://github.com/cypress-io/cypress/tree/develop/npm/svelte)
- [`@cypress/angular`](https://github.com/cypress-io/cypress/tree/develop/npm/angular)
## What is a Mount Adapter?
All Component Tests require a component to be **mounted**. This is generally done with a custom command, `cy.mount` by default.
### Requirements
All the functionality used to create the first party Mount adapters is available to support third parties adapters. At minimum, a Mount Adapter must:
- Receive a component as the first argument. This could be class, function etc - depends on the framework.
- Return a Cypress Chainable (for example using `cy.wrap`) that resolves whatever is idiomatic for your framework
- Call `getContainerEl` to access the root DOM element
In addition, we recommend that Mount Adapters:
- call `setupHooks` to register the required lifecycle hooks for `@cypress/mount-utils` to work
### Example Mount Adapter: Web Components
Here's a simple yet realistic example of Mount Adapter targeting Web Components. It uses utilities from this package (`@cypress/mount-utils`) This is recommended, so your adapter behaves similar to the first party Mount Adapters.
```ts
import {
ROOT_SELECTOR,
setupHooks,
getContainerEl
} from "@cypress/mount-utils";
Cypress.on("run:start", () => {
// Consider doing a check to ensure your adapter only runs in Component Testing mode.
if (Cypress.testingType !== "component") {
return;
}
Cypress.on("test:before:run", () => {
// Do some cleanup from previous test - for example, clear the DOM.
getContainerEl().innerHTML = "";
});
});
function maybeRegisterComponent<T extends CustomElementConstructor>(
name: string,
webComponent: T
) {
// Avoid double-registering a Web Component.
if (window.customElements.get(name)) {
return;
}
window.customElements.define(name, webComponent);
}
export function mount(
webComponent: CustomElementConstructor
): Cypress.Chainable {
// Get root selector defined in `cypress/support.component-index.html
const $root = document.querySelector(ROOT_SELECTOR)!;
// Change to kebab-case to comply with Web Component naming convention
const name = webComponent.name
.replace(/([a-z09])([A-Z])/g, "$1-$2")
.toLowerCase();
/// Register Web Component
maybeRegisterComponent(name, webComponent);
// Render HTML containing component.
$root.innerHTML = `<${name} id="root"></${name}>`;
// Log a messsage in the Command Log.
Cypress.log({
name: "mount",
message: [`<${name} ... />`],
});
// Return a `Cypress.Chainable` that returns whatever is idiomatic
// in the framework your mount adapter targets.
return cy.wrap(document.querySelector("#root"), { log: false });
}
// Setup Cypress lifecycle hooks.
setupHooks();
```
Usage:
```ts
// User will generally register a `cy.mount` command in `cypress/support/component.js`:
import { mount } from '@package/cypress-web-components'
Cypress.Commands.add('mount', mount)
// Test
export class WebCounter extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `
<div>
<button>Counter</button>
</div>`;
}
}
describe('web-component.cy.ts', () => {
it('playground', () => {
cy.mount(WebCounter)
})
})
```
For more robust, production ready examples, check out our first party adapters.
## Compatibility
| @cypress/mount-utils | cypress |
| -------------------- | ------- |
| <= v1 | <= v9 |
| >= v2 | >= v10 |
## Changelog
[Changelog](./CHANGELOG.md)

40
node_modules/cypress/mount-utils/dist/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,40 @@
export declare const ROOT_SELECTOR = "[data-cy-root]";
/**
* Gets the root element used to mount the component.
* @returns {HTMLElement} The root element
* @throws {Error} If the root element is not found
*/
export declare const getContainerEl: () => HTMLElement;
export declare function checkForRemovedStyleOptions(mountingOptions: Record<string, any>): void;
/**
* Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
* @param optionalCallback Callback to be called before the next test runs
*/
export declare function setupHooks(optionalCallback?: Function): void;
/**
* Remove any style or extra link elements from the iframe placeholder
* left from any previous test
*
* Removed as of Cypress 11.0.0
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export declare function cleanupStyles(): void;
/**
* Additional styles to inject into the document.
* A component might need 3rd party libraries from CDN,
* local CSS files and custom styles.
*
* Removed as of Cypress 11.0.0.
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export type StyleOptions = unknown;
/**
* Injects custom style text or CSS file or 3rd party style resources
* into the given document.
*
* Removed as of Cypress 11.0.0.
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export declare const injectStylesBeforeElement: (options: Partial<StyleOptions & {
log: boolean;
}>, document: Document, el: HTMLElement | null) => void;

68
node_modules/cypress/mount-utils/dist/index.js generated vendored Normal file
View File

@@ -0,0 +1,68 @@
export const ROOT_SELECTOR = '[data-cy-root]';
/**
* Gets the root element used to mount the component.
* @returns {HTMLElement} The root element
* @throws {Error} If the root element is not found
*/
export const getContainerEl = () => {
const el = document.querySelector(ROOT_SELECTOR);
if (el) {
return el;
}
throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`);
};
export function checkForRemovedStyleOptions(mountingOptions) {
for (const key of ['cssFile', 'cssFiles', 'style', 'styles', 'stylesheet', 'stylesheets']) {
if (mountingOptions[key]) {
Cypress.utils.throwErrByPath('mount.removed_style_mounting_options', key);
}
}
}
/**
* Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
* @param optionalCallback Callback to be called before the next test runs
*/
export function setupHooks(optionalCallback) {
// We don't want CT side effects to run when e2e
// testing so we early return.
// System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
if (Cypress.testingType !== 'component') {
return;
}
// When running component specs, we cannot allow "cy.visit"
// because it will wipe out our preparation work, and does not make much sense
// thus we overwrite "cy.visit" to throw an error
Cypress.Commands.overwrite('visit', () => {
throw new Error('cy.visit from a component spec is not allowed');
});
Cypress.Commands.overwrite('session', () => {
throw new Error('cy.session from a component spec is not allowed');
});
Cypress.Commands.overwrite('origin', () => {
throw new Error('cy.origin from a component spec is not allowed');
});
// @ts-ignore
Cypress.on('test:before:after:run:async', () => {
optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
});
}
/**
* Remove any style or extra link elements from the iframe placeholder
* left from any previous test
*
* Removed as of Cypress 11.0.0
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export function cleanupStyles() {
Cypress.utils.throwErrByPath('mount.cleanup_styles');
}
/**
* Injects custom style text or CSS file or 3rd party style resources
* into the given document.
*
* Removed as of Cypress 11.0.0.
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export const injectStylesBeforeElement = (options, document, el) => {
Cypress.utils.throwErrByPath('mount.inject_styles_before_element');
};

140
node_modules/cypress/mount-utils/mount-utils/README.md generated vendored Normal file
View File

@@ -0,0 +1,140 @@
# @cypress/mount-utils
> **Note** this package is not meant to be used outside of cypress component testing.
This library exports some shared types and utility functions designed to build adapters for components frameworks.
It is used in:
- [`@cypress/react`](https://github.com/cypress-io/cypress/tree/develop/npm/react)
- [`@cypress/vue`](https://github.com/cypress-io/cypress/tree/develop/npm/vue)
- [`@cypress/svelte`](https://github.com/cypress-io/cypress/tree/develop/npm/svelte)
- [`@cypress/angular`](https://github.com/cypress-io/cypress/tree/develop/npm/angular)
## What is a Mount Adapter?
All Component Tests require a component to be **mounted**. This is generally done with a custom command, `cy.mount` by default.
### Requirements
All the functionality used to create the first party Mount adapters is available to support third parties adapters. At minimum, a Mount Adapter must:
- Receive a component as the first argument. This could be class, function etc - depends on the framework.
- Return a Cypress Chainable (for example using `cy.wrap`) that resolves whatever is idiomatic for your framework
- Call `getContainerEl` to access the root DOM element
In addition, we recommend that Mount Adapters:
- call `setupHooks` to register the required lifecycle hooks for `@cypress/mount-utils` to work
### Example Mount Adapter: Web Components
Here's a simple yet realistic example of Mount Adapter targeting Web Components. It uses utilities from this package (`@cypress/mount-utils`) This is recommended, so your adapter behaves similar to the first party Mount Adapters.
```ts
import {
ROOT_SELECTOR,
setupHooks,
getContainerEl
} from "@cypress/mount-utils";
Cypress.on("run:start", () => {
// Consider doing a check to ensure your adapter only runs in Component Testing mode.
if (Cypress.testingType !== "component") {
return;
}
Cypress.on("test:before:run", () => {
// Do some cleanup from previous test - for example, clear the DOM.
getContainerEl().innerHTML = "";
});
});
function maybeRegisterComponent<T extends CustomElementConstructor>(
name: string,
webComponent: T
) {
// Avoid double-registering a Web Component.
if (window.customElements.get(name)) {
return;
}
window.customElements.define(name, webComponent);
}
export function mount(
webComponent: CustomElementConstructor
): Cypress.Chainable {
// Get root selector defined in `cypress/support.component-index.html
const $root = document.querySelector(ROOT_SELECTOR)!;
// Change to kebab-case to comply with Web Component naming convention
const name = webComponent.name
.replace(/([a-z09])([A-Z])/g, "$1-$2")
.toLowerCase();
/// Register Web Component
maybeRegisterComponent(name, webComponent);
// Render HTML containing component.
$root.innerHTML = `<${name} id="root"></${name}>`;
// Log a messsage in the Command Log.
Cypress.log({
name: "mount",
message: [`<${name} ... />`],
});
// Return a `Cypress.Chainable` that returns whatever is idiomatic
// in the framework your mount adapter targets.
return cy.wrap(document.querySelector("#root"), { log: false });
}
// Setup Cypress lifecycle hooks.
setupHooks();
```
Usage:
```ts
// User will generally register a `cy.mount` command in `cypress/support/component.js`:
import { mount } from '@package/cypress-web-components'
Cypress.Commands.add('mount', mount)
// Test
export class WebCounter extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.innerHTML = `
<div>
<button>Counter</button>
</div>`;
}
}
describe('web-component.cy.ts', () => {
it('playground', () => {
cy.mount(WebCounter)
})
})
```
For more robust, production ready examples, check out our first party adapters.
## Compatibility
| @cypress/mount-utils | cypress |
| -------------------- | ------- |
| <= v1 | <= v9 |
| >= v2 | >= v10 |
## Changelog
[Changelog](./CHANGELOG.md)

View File

@@ -0,0 +1,40 @@
export declare const ROOT_SELECTOR = "[data-cy-root]";
/**
* Gets the root element used to mount the component.
* @returns {HTMLElement} The root element
* @throws {Error} If the root element is not found
*/
export declare const getContainerEl: () => HTMLElement;
export declare function checkForRemovedStyleOptions(mountingOptions: Record<string, any>): void;
/**
* Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
* @param optionalCallback Callback to be called before the next test runs
*/
export declare function setupHooks(optionalCallback?: Function): void;
/**
* Remove any style or extra link elements from the iframe placeholder
* left from any previous test
*
* Removed as of Cypress 11.0.0
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export declare function cleanupStyles(): void;
/**
* Additional styles to inject into the document.
* A component might need 3rd party libraries from CDN,
* local CSS files and custom styles.
*
* Removed as of Cypress 11.0.0.
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export type StyleOptions = unknown;
/**
* Injects custom style text or CSS file or 3rd party style resources
* into the given document.
*
* Removed as of Cypress 11.0.0.
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export declare const injectStylesBeforeElement: (options: Partial<StyleOptions & {
log: boolean;
}>, document: Document, el: HTMLElement | null) => void;

View File

@@ -0,0 +1,68 @@
export const ROOT_SELECTOR = '[data-cy-root]';
/**
* Gets the root element used to mount the component.
* @returns {HTMLElement} The root element
* @throws {Error} If the root element is not found
*/
export const getContainerEl = () => {
const el = document.querySelector(ROOT_SELECTOR);
if (el) {
return el;
}
throw Error(`No element found that matches selector ${ROOT_SELECTOR}. Please add a root element with data-cy-root attribute to your "component-index.html" file so that Cypress can attach your component to the DOM.`);
};
export function checkForRemovedStyleOptions(mountingOptions) {
for (const key of ['cssFile', 'cssFiles', 'style', 'styles', 'stylesheet', 'stylesheets']) {
if (mountingOptions[key]) {
Cypress.utils.throwErrByPath('mount.removed_style_mounting_options', key);
}
}
}
/**
* Utility function to register CT side effects and run cleanup code during the "test:before:run" Cypress hook
* @param optionalCallback Callback to be called before the next test runs
*/
export function setupHooks(optionalCallback) {
// We don't want CT side effects to run when e2e
// testing so we early return.
// System test to verify CT side effects do not pollute e2e: system-tests/test/e2e_with_mount_import_spec.ts
if (Cypress.testingType !== 'component') {
return;
}
// When running component specs, we cannot allow "cy.visit"
// because it will wipe out our preparation work, and does not make much sense
// thus we overwrite "cy.visit" to throw an error
Cypress.Commands.overwrite('visit', () => {
throw new Error('cy.visit from a component spec is not allowed');
});
Cypress.Commands.overwrite('session', () => {
throw new Error('cy.session from a component spec is not allowed');
});
Cypress.Commands.overwrite('origin', () => {
throw new Error('cy.origin from a component spec is not allowed');
});
// @ts-ignore
Cypress.on('test:before:after:run:async', () => {
optionalCallback === null || optionalCallback === void 0 ? void 0 : optionalCallback();
});
}
/**
* Remove any style or extra link elements from the iframe placeholder
* left from any previous test
*
* Removed as of Cypress 11.0.0
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export function cleanupStyles() {
Cypress.utils.throwErrByPath('mount.cleanup_styles');
}
/**
* Injects custom style text or CSS file or 3rd party style resources
* into the given document.
*
* Removed as of Cypress 11.0.0.
* @see https://on.cypress.io/migration-11-0-0-component-testing-updates
*/
export const injectStylesBeforeElement = (options, document, el) => {
Cypress.utils.throwErrByPath('mount.inject_styles_before_element');
};

View File

@@ -0,0 +1,46 @@
{
"name": "@cypress/mount-utils",
"version": "0.0.0-development",
"description": "Shared utilities for the various component testing adapters",
"main": "dist/index.js",
"scripts": {
"build": "tsc || echo 'built, with type errors'",
"postbuild": "node ../../scripts/sync-exported-npm-with-cli.js",
"check-ts": "tsc --noEmit",
"lint": "eslint --ext .js,.ts,.json, .",
"watch": "tsc -w"
},
"dependencies": {},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-node-resolve": "^11.1.1",
"rollup": "3.7.3",
"rollup-plugin-dts": "5.0.0",
"rollup-plugin-typescript2": "^0.29.0",
"typescript": "^5.4.5"
},
"files": [
"dist"
],
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/tree/develop/npm/mount-utils#readme",
"bugs": "https://github.com/cypress-io/cypress/issues/new?template=1-bug-report.md",
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"outputs": [
"{workspaceRoot}/cli/mount-utils",
"{projectRoot}/dist"
]
}
}
}
}

46
node_modules/cypress/mount-utils/package.json generated vendored Normal file
View File

@@ -0,0 +1,46 @@
{
"name": "@cypress/mount-utils",
"version": "0.0.0-development",
"description": "Shared utilities for the various component testing adapters",
"main": "dist/index.js",
"scripts": {
"build": "tsc || echo 'built, with type errors'",
"postbuild": "node ../../scripts/sync-exported-npm-with-cli.js",
"check-ts": "tsc --noEmit",
"lint": "eslint --ext .js,.ts,.json, .",
"watch": "tsc -w"
},
"dependencies": {},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-node-resolve": "^11.1.1",
"rollup": "3.7.3",
"rollup-plugin-dts": "5.0.0",
"rollup-plugin-typescript2": "^0.29.0",
"typescript": "^5.4.5"
},
"files": [
"dist"
],
"types": "dist/index.d.ts",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/cypress-io/cypress.git"
},
"homepage": "https://github.com/cypress-io/cypress/tree/develop/npm/mount-utils#readme",
"bugs": "https://github.com/cypress-io/cypress/issues/new?template=1-bug-report.md",
"publishConfig": {
"access": "public"
},
"nx": {
"targets": {
"build": {
"outputs": [
"{workspaceRoot}/cli/mount-utils",
"{projectRoot}/dist"
]
}
}
}
}

16
node_modules/cypress/node_modules/.bin/semver generated vendored Normal file
View File

@@ -0,0 +1,16 @@
#!/bin/sh
basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
case `uname` in
*CYGWIN*|*MINGW*|*MSYS*)
if command -v cygpath > /dev/null 2>&1; then
basedir=`cygpath -w "$basedir"`
fi
;;
esac
if [ -x "$basedir/node" ]; then
exec "$basedir/node" "$basedir/../semver/bin/semver.js" "$@"
else
exec node "$basedir/../semver/bin/semver.js" "$@"
fi

17
node_modules/cypress/node_modules/.bin/semver.cmd generated vendored Normal file
View File

@@ -0,0 +1,17 @@
@ECHO off
GOTO start
:find_dp0
SET dp0=%~dp0
EXIT /b
:start
SETLOCAL
CALL :find_dp0
IF EXIST "%dp0%\node.exe" (
SET "_prog=%dp0%\node.exe"
) ELSE (
SET "_prog=node"
SET PATHEXT=%PATHEXT:;.JS;=;%
)
endLocal & goto #_undefined_# 2>NUL || title %COMSPEC% & "%_prog%" "%dp0%\..\semver\bin\semver.js" %*

28
node_modules/cypress/node_modules/.bin/semver.ps1 generated vendored Normal file
View File

@@ -0,0 +1,28 @@
#!/usr/bin/env pwsh
$basedir=Split-Path $MyInvocation.MyCommand.Definition -Parent
$exe=""
if ($PSVersionTable.PSVersion -lt "6.0" -or $IsWindows) {
# Fix case when both the Windows and Linux builds of Node
# are installed in the same directory
$exe=".exe"
}
$ret=0
if (Test-Path "$basedir/node$exe") {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
} else {
& "$basedir/node$exe" "$basedir/../semver/bin/semver.js" $args
}
$ret=$LASTEXITCODE
} else {
# Support pipeline input
if ($MyInvocation.ExpectingInput) {
$input | & "node$exe" "$basedir/../semver/bin/semver.js" $args
} else {
& "node$exe" "$basedir/../semver/bin/semver.js" $args
}
$ret=$LASTEXITCODE
}
exit $ret

View File

@@ -0,0 +1,345 @@
declare type CSSColor =
| 'aliceblue'
| 'antiquewhite'
| 'aqua'
| 'aquamarine'
| 'azure'
| 'beige'
| 'bisque'
| 'black'
| 'blanchedalmond'
| 'blue'
| 'blueviolet'
| 'brown'
| 'burlywood'
| 'cadetblue'
| 'chartreuse'
| 'chocolate'
| 'coral'
| 'cornflowerblue'
| 'cornsilk'
| 'crimson'
| 'cyan'
| 'darkblue'
| 'darkcyan'
| 'darkgoldenrod'
| 'darkgray'
| 'darkgreen'
| 'darkgrey'
| 'darkkhaki'
| 'darkmagenta'
| 'darkolivegreen'
| 'darkorange'
| 'darkorchid'
| 'darkred'
| 'darksalmon'
| 'darkseagreen'
| 'darkslateblue'
| 'darkslategray'
| 'darkslategrey'
| 'darkturquoise'
| 'darkviolet'
| 'deeppink'
| 'deepskyblue'
| 'dimgray'
| 'dimgrey'
| 'dodgerblue'
| 'firebrick'
| 'floralwhite'
| 'forestgreen'
| 'fuchsia'
| 'gainsboro'
| 'ghostwhite'
| 'gold'
| 'goldenrod'
| 'gray'
| 'green'
| 'greenyellow'
| 'grey'
| 'honeydew'
| 'hotpink'
| 'indianred'
| 'indigo'
| 'ivory'
| 'khaki'
| 'lavender'
| 'lavenderblush'
| 'lawngreen'
| 'lemonchiffon'
| 'lightblue'
| 'lightcoral'
| 'lightcyan'
| 'lightgoldenrodyellow'
| 'lightgray'
| 'lightgreen'
| 'lightgrey'
| 'lightpink'
| 'lightsalmon'
| 'lightseagreen'
| 'lightskyblue'
| 'lightslategray'
| 'lightslategrey'
| 'lightsteelblue'
| 'lightyellow'
| 'lime'
| 'limegreen'
| 'linen'
| 'magenta'
| 'maroon'
| 'mediumaquamarine'
| 'mediumblue'
| 'mediumorchid'
| 'mediumpurple'
| 'mediumseagreen'
| 'mediumslateblue'
| 'mediumspringgreen'
| 'mediumturquoise'
| 'mediumvioletred'
| 'midnightblue'
| 'mintcream'
| 'mistyrose'
| 'moccasin'
| 'navajowhite'
| 'navy'
| 'oldlace'
| 'olive'
| 'olivedrab'
| 'orange'
| 'orangered'
| 'orchid'
| 'palegoldenrod'
| 'palegreen'
| 'paleturquoise'
| 'palevioletred'
| 'papayawhip'
| 'peachpuff'
| 'peru'
| 'pink'
| 'plum'
| 'powderblue'
| 'purple'
| 'rebeccapurple'
| 'red'
| 'rosybrown'
| 'royalblue'
| 'saddlebrown'
| 'salmon'
| 'sandybrown'
| 'seagreen'
| 'seashell'
| 'sienna'
| 'silver'
| 'skyblue'
| 'slateblue'
| 'slategray'
| 'slategrey'
| 'snow'
| 'springgreen'
| 'steelblue'
| 'tan'
| 'teal'
| 'thistle'
| 'tomato'
| 'turquoise'
| 'violet'
| 'wheat'
| 'white'
| 'whitesmoke'
| 'yellow'
| 'yellowgreen';
declare namespace ansiStyles {
interface ColorConvert {
/**
The RGB color space.
@param red - (`0`-`255`)
@param green - (`0`-`255`)
@param blue - (`0`-`255`)
*/
rgb(red: number, green: number, blue: number): string;
/**
The RGB HEX color space.
@param hex - A hexadecimal string containing RGB data.
*/
hex(hex: string): string;
/**
@param keyword - A CSS color name.
*/
keyword(keyword: CSSColor): string;
/**
The HSL color space.
@param hue - (`0`-`360`)
@param saturation - (`0`-`100`)
@param lightness - (`0`-`100`)
*/
hsl(hue: number, saturation: number, lightness: number): string;
/**
The HSV color space.
@param hue - (`0`-`360`)
@param saturation - (`0`-`100`)
@param value - (`0`-`100`)
*/
hsv(hue: number, saturation: number, value: number): string;
/**
The HSV color space.
@param hue - (`0`-`360`)
@param whiteness - (`0`-`100`)
@param blackness - (`0`-`100`)
*/
hwb(hue: number, whiteness: number, blackness: number): string;
/**
Use a [4-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4-bit) to set text color.
*/
ansi(ansi: number): string;
/**
Use an [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
*/
ansi256(ansi: number): string;
}
interface CSPair {
/**
The ANSI terminal control sequence for starting this style.
*/
readonly open: string;
/**
The ANSI terminal control sequence for ending this style.
*/
readonly close: string;
}
interface ColorBase {
readonly ansi: ColorConvert;
readonly ansi256: ColorConvert;
readonly ansi16m: ColorConvert;
/**
The ANSI terminal control sequence for ending this color.
*/
readonly close: string;
}
interface Modifier {
/**
Resets the current color chain.
*/
readonly reset: CSPair;
/**
Make text bold.
*/
readonly bold: CSPair;
/**
Emitting only a small amount of light.
*/
readonly dim: CSPair;
/**
Make text italic. (Not widely supported)
*/
readonly italic: CSPair;
/**
Make text underline. (Not widely supported)
*/
readonly underline: CSPair;
/**
Inverse background and foreground colors.
*/
readonly inverse: CSPair;
/**
Prints the text, but makes it invisible.
*/
readonly hidden: CSPair;
/**
Puts a horizontal line through the center of the text. (Not widely supported)
*/
readonly strikethrough: CSPair;
}
interface ForegroundColor {
readonly black: CSPair;
readonly red: CSPair;
readonly green: CSPair;
readonly yellow: CSPair;
readonly blue: CSPair;
readonly cyan: CSPair;
readonly magenta: CSPair;
readonly white: CSPair;
/**
Alias for `blackBright`.
*/
readonly gray: CSPair;
/**
Alias for `blackBright`.
*/
readonly grey: CSPair;
readonly blackBright: CSPair;
readonly redBright: CSPair;
readonly greenBright: CSPair;
readonly yellowBright: CSPair;
readonly blueBright: CSPair;
readonly cyanBright: CSPair;
readonly magentaBright: CSPair;
readonly whiteBright: CSPair;
}
interface BackgroundColor {
readonly bgBlack: CSPair;
readonly bgRed: CSPair;
readonly bgGreen: CSPair;
readonly bgYellow: CSPair;
readonly bgBlue: CSPair;
readonly bgCyan: CSPair;
readonly bgMagenta: CSPair;
readonly bgWhite: CSPair;
/**
Alias for `bgBlackBright`.
*/
readonly bgGray: CSPair;
/**
Alias for `bgBlackBright`.
*/
readonly bgGrey: CSPair;
readonly bgBlackBright: CSPair;
readonly bgRedBright: CSPair;
readonly bgGreenBright: CSPair;
readonly bgYellowBright: CSPair;
readonly bgBlueBright: CSPair;
readonly bgCyanBright: CSPair;
readonly bgMagentaBright: CSPair;
readonly bgWhiteBright: CSPair;
}
}
declare const ansiStyles: {
readonly modifier: ansiStyles.Modifier;
readonly color: ansiStyles.ForegroundColor & ansiStyles.ColorBase;
readonly bgColor: ansiStyles.BackgroundColor & ansiStyles.ColorBase;
readonly codes: ReadonlyMap<number, number>;
} & ansiStyles.BackgroundColor & ansiStyles.ForegroundColor & ansiStyles.Modifier;
export = ansiStyles;

163
node_modules/cypress/node_modules/ansi-styles/index.js generated vendored Normal file
View File

@@ -0,0 +1,163 @@
'use strict';
const wrapAnsi16 = (fn, offset) => (...args) => {
const code = fn(...args);
return `\u001B[${code + offset}m`;
};
const wrapAnsi256 = (fn, offset) => (...args) => {
const code = fn(...args);
return `\u001B[${38 + offset};5;${code}m`;
};
const wrapAnsi16m = (fn, offset) => (...args) => {
const rgb = fn(...args);
return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
};
const ansi2ansi = n => n;
const rgb2rgb = (r, g, b) => [r, g, b];
const setLazyProperty = (object, property, get) => {
Object.defineProperty(object, property, {
get: () => {
const value = get();
Object.defineProperty(object, property, {
value,
enumerable: true,
configurable: true
});
return value;
},
enumerable: true,
configurable: true
});
};
/** @type {typeof import('color-convert')} */
let colorConvert;
const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
if (colorConvert === undefined) {
colorConvert = require('color-convert');
}
const offset = isBackground ? 10 : 0;
const styles = {};
for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace;
if (sourceSpace === targetSpace) {
styles[name] = wrap(identity, offset);
} else if (typeof suite === 'object') {
styles[name] = wrap(suite[targetSpace], offset);
}
}
return styles;
};
function assembleStyles() {
const codes = new Map();
const styles = {
modifier: {
reset: [0, 0],
// 21 isn't widely supported and 22 does the same thing
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
color: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
// Bright color
blackBright: [90, 39],
redBright: [91, 39],
greenBright: [92, 39],
yellowBright: [93, 39],
blueBright: [94, 39],
magentaBright: [95, 39],
cyanBright: [96, 39],
whiteBright: [97, 39]
},
bgColor: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
// Bright color
bgBlackBright: [100, 49],
bgRedBright: [101, 49],
bgGreenBright: [102, 49],
bgYellowBright: [103, 49],
bgBlueBright: [104, 49],
bgMagentaBright: [105, 49],
bgCyanBright: [106, 49],
bgWhiteBright: [107, 49]
}
};
// Alias bright black as gray (and grey)
styles.color.gray = styles.color.blackBright;
styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
styles.color.grey = styles.color.blackBright;
styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
for (const [groupName, group] of Object.entries(styles)) {
for (const [styleName, style] of Object.entries(group)) {
styles[styleName] = {
open: `\u001B[${style[0]}m`,
close: `\u001B[${style[1]}m`
};
group[styleName] = styles[styleName];
codes.set(style[0], style[1]);
}
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
}
Object.defineProperty(styles, 'codes', {
value: codes,
enumerable: false
});
styles.color.close = '\u001B[39m';
styles.bgColor.close = '\u001B[49m';
setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false));
setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false));
setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false));
setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true));
setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true));
setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true));
return styles;
}
// Make the export immutable
Object.defineProperty(module, 'exports', {
enumerable: true,
get: assembleStyles
});

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,56 @@
{
"name": "ansi-styles",
"version": "4.3.0",
"description": "ANSI escape codes for styling strings in the terminal",
"license": "MIT",
"repository": "chalk/ansi-styles",
"funding": "https://github.com/chalk/ansi-styles?sponsor=1",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd",
"screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"color-convert": "^2.0.1"
},
"devDependencies": {
"@types/color-convert": "^1.9.0",
"ava": "^2.3.0",
"svg-term-cli": "^2.1.1",
"tsd": "^0.11.0",
"xo": "^0.25.3"
}
}

152
node_modules/cypress/node_modules/ansi-styles/readme.md generated vendored Normal file
View File

@@ -0,0 +1,152 @@
# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
<img src="screenshot.svg" width="900">
## Install
```
$ npm install ansi-styles
```
## Usage
```js
const style = require('ansi-styles');
console.log(`${style.green.open}Hello world!${style.green.close}`);
// Color conversion between 16/256/truecolor
// NOTE: If conversion goes to 16 colors or 256 colors, the original color
// may be degraded to fit that color palette. This means terminals
// that do not support 16 million colors will best-match the
// original color.
console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
console.log(style.color.ansi16m.hex('#abcdef') + 'Hello world!' + style.color.close);
```
## API
Each style has an `open` and `close` property.
## Styles
### Modifiers
- `reset`
- `bold`
- `dim`
- `italic` *(Not widely supported)*
- `underline`
- `inverse`
- `hidden`
- `strikethrough` *(Not widely supported)*
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Advanced usage
By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
- `style.modifier`
- `style.color`
- `style.bgColor`
###### Example
```js
console.log(style.color.green.open);
```
Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
###### Example
```js
console.log(style.codes.get(36));
//=> 39
```
## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
The following color spaces from `color-convert` are supported:
- `rgb`
- `hex`
- `keyword`
- `hsl`
- `hsv`
- `hwb`
- `ansi`
- `ansi256`
To use these, call the associated conversion function with the intended output, for example:
```js
style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
```
## Related
- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## For enterprise
Available as part of the Tidelift Subscription.
The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

415
node_modules/cypress/node_modules/chalk/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,415 @@
/**
Basic foreground colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type ForegroundColor =
| 'black'
| 'red'
| 'green'
| 'yellow'
| 'blue'
| 'magenta'
| 'cyan'
| 'white'
| 'gray'
| 'grey'
| 'blackBright'
| 'redBright'
| 'greenBright'
| 'yellowBright'
| 'blueBright'
| 'magentaBright'
| 'cyanBright'
| 'whiteBright';
/**
Basic background colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type BackgroundColor =
| 'bgBlack'
| 'bgRed'
| 'bgGreen'
| 'bgYellow'
| 'bgBlue'
| 'bgMagenta'
| 'bgCyan'
| 'bgWhite'
| 'bgGray'
| 'bgGrey'
| 'bgBlackBright'
| 'bgRedBright'
| 'bgGreenBright'
| 'bgYellowBright'
| 'bgBlueBright'
| 'bgMagentaBright'
| 'bgCyanBright'
| 'bgWhiteBright';
/**
Basic colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type Color = ForegroundColor | BackgroundColor;
declare type Modifiers =
| 'reset'
| 'bold'
| 'dim'
| 'italic'
| 'underline'
| 'inverse'
| 'hidden'
| 'strikethrough'
| 'visible';
declare namespace chalk {
/**
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
type Level = 0 | 1 | 2 | 3;
interface Options {
/**
Specify the color support for Chalk.
By default, color support is automatically detected based on the environment.
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
level?: Level;
}
/**
Return a new Chalk instance.
*/
type Instance = new (options?: Options) => Chalk;
/**
Detect whether the terminal supports color.
*/
interface ColorSupport {
/**
The color level used by Chalk.
*/
level: Level;
/**
Return whether Chalk supports basic 16 colors.
*/
hasBasic: boolean;
/**
Return whether Chalk supports ANSI 256 colors.
*/
has256: boolean;
/**
Return whether Chalk supports Truecolor 16 million colors.
*/
has16m: boolean;
}
interface ChalkFunction {
/**
Use a template string.
@remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
@example
```
import chalk = require('chalk');
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
```
@example
```
import chalk = require('chalk');
log(chalk.red.bgBlack`2 + 3 = {bold ${2 + 3}}`)
```
*/
(text: TemplateStringsArray, ...placeholders: unknown[]): string;
(...text: unknown[]): string;
}
interface Chalk extends ChalkFunction {
/**
Return a new Chalk instance.
*/
Instance: Instance;
/**
The color support for Chalk.
By default, color support is automatically detected based on the environment.
Levels:
- `0` - All colors disabled.
- `1` - Basic 16 colors support.
- `2` - ANSI 256 colors support.
- `3` - Truecolor 16 million colors support.
*/
level: Level;
/**
Use HEX value to set text color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.hex('#DEADED');
```
*/
hex(color: string): Chalk;
/**
Use keyword color value to set text color.
@param color - Keyword value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.keyword('orange');
```
*/
keyword(color: string): Chalk;
/**
Use RGB values to set text color.
*/
rgb(red: number, green: number, blue: number): Chalk;
/**
Use HSL values to set text color.
*/
hsl(hue: number, saturation: number, lightness: number): Chalk;
/**
Use HSV values to set text color.
*/
hsv(hue: number, saturation: number, value: number): Chalk;
/**
Use HWB values to set text color.
*/
hwb(hue: number, whiteness: number, blackness: number): Chalk;
/**
Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set text color.
30 <= code && code < 38 || 90 <= code && code < 98
For example, 31 for red, 91 for redBright.
*/
ansi(code: number): Chalk;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
*/
ansi256(index: number): Chalk;
/**
Use HEX value to set background color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.bgHex('#DEADED');
```
*/
bgHex(color: string): Chalk;
/**
Use keyword color value to set background color.
@param color - Keyword value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.bgKeyword('orange');
```
*/
bgKeyword(color: string): Chalk;
/**
Use RGB values to set background color.
*/
bgRgb(red: number, green: number, blue: number): Chalk;
/**
Use HSL values to set background color.
*/
bgHsl(hue: number, saturation: number, lightness: number): Chalk;
/**
Use HSV values to set background color.
*/
bgHsv(hue: number, saturation: number, value: number): Chalk;
/**
Use HWB values to set background color.
*/
bgHwb(hue: number, whiteness: number, blackness: number): Chalk;
/**
Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set background color.
30 <= code && code < 38 || 90 <= code && code < 98
For example, 31 for red, 91 for redBright.
Use the foreground code, not the background code (for example, not 41, nor 101).
*/
bgAnsi(code: number): Chalk;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set background color.
*/
bgAnsi256(index: number): Chalk;
/**
Modifier: Resets the current color chain.
*/
readonly reset: Chalk;
/**
Modifier: Make text bold.
*/
readonly bold: Chalk;
/**
Modifier: Emitting only a small amount of light.
*/
readonly dim: Chalk;
/**
Modifier: Make text italic. (Not widely supported)
*/
readonly italic: Chalk;
/**
Modifier: Make text underline. (Not widely supported)
*/
readonly underline: Chalk;
/**
Modifier: Inverse background and foreground colors.
*/
readonly inverse: Chalk;
/**
Modifier: Prints the text, but makes it invisible.
*/
readonly hidden: Chalk;
/**
Modifier: Puts a horizontal line through the center of the text. (Not widely supported)
*/
readonly strikethrough: Chalk;
/**
Modifier: Prints the text only when Chalk has a color support level > 0.
Can be useful for things that are purely cosmetic.
*/
readonly visible: Chalk;
readonly black: Chalk;
readonly red: Chalk;
readonly green: Chalk;
readonly yellow: Chalk;
readonly blue: Chalk;
readonly magenta: Chalk;
readonly cyan: Chalk;
readonly white: Chalk;
/*
Alias for `blackBright`.
*/
readonly gray: Chalk;
/*
Alias for `blackBright`.
*/
readonly grey: Chalk;
readonly blackBright: Chalk;
readonly redBright: Chalk;
readonly greenBright: Chalk;
readonly yellowBright: Chalk;
readonly blueBright: Chalk;
readonly magentaBright: Chalk;
readonly cyanBright: Chalk;
readonly whiteBright: Chalk;
readonly bgBlack: Chalk;
readonly bgRed: Chalk;
readonly bgGreen: Chalk;
readonly bgYellow: Chalk;
readonly bgBlue: Chalk;
readonly bgMagenta: Chalk;
readonly bgCyan: Chalk;
readonly bgWhite: Chalk;
/*
Alias for `bgBlackBright`.
*/
readonly bgGray: Chalk;
/*
Alias for `bgBlackBright`.
*/
readonly bgGrey: Chalk;
readonly bgBlackBright: Chalk;
readonly bgRedBright: Chalk;
readonly bgGreenBright: Chalk;
readonly bgYellowBright: Chalk;
readonly bgBlueBright: Chalk;
readonly bgMagentaBright: Chalk;
readonly bgCyanBright: Chalk;
readonly bgWhiteBright: Chalk;
}
}
/**
Main Chalk object that allows to chain styles together.
Call the last one as a method with a string argument.
Order doesn't matter, and later styles take precedent in case of a conflict.
This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
*/
declare const chalk: chalk.Chalk & chalk.ChalkFunction & {
supportsColor: chalk.ColorSupport | false;
Level: chalk.Level;
Color: Color;
ForegroundColor: ForegroundColor;
BackgroundColor: BackgroundColor;
Modifiers: Modifiers;
stderr: chalk.Chalk & {supportsColor: chalk.ColorSupport | false};
};
export = chalk;

9
node_modules/cypress/node_modules/chalk/license generated vendored Normal file
View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,5 @@
'use strict';
module.exports = {
stdout: false,
stderr: false
};

View File

@@ -0,0 +1,135 @@
'use strict';
const os = require('os');
const tty = require('tty');
const hasFlag = require('has-flag');
const {env} = process;
let forceColor;
if (hasFlag('no-color') ||
hasFlag('no-colors') ||
hasFlag('color=false') ||
hasFlag('color=never')) {
forceColor = 0;
} else if (hasFlag('color') ||
hasFlag('colors') ||
hasFlag('color=true') ||
hasFlag('color=always')) {
forceColor = 1;
}
if ('FORCE_COLOR' in env) {
if (env.FORCE_COLOR === 'true') {
forceColor = 1;
} else if (env.FORCE_COLOR === 'false') {
forceColor = 0;
} else {
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
}
}
function translateLevel(level) {
if (level === 0) {
return false;
}
return {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3
};
}
function supportsColor(haveStream, streamIsTTY) {
if (forceColor === 0) {
return 0;
}
if (hasFlag('color=16m') ||
hasFlag('color=full') ||
hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
if (haveStream && !streamIsTTY && forceColor === undefined) {
return 0;
}
const min = forceColor || 0;
if (env.TERM === 'dumb') {
return min;
}
if (process.platform === 'win32') {
// Windows 10 build 10586 is the first Windows release that supports 256 colors.
// Windows 10 build 14931 is the first release that supports 16m/TrueColor.
const osRelease = os.release().split('.');
if (
Number(osRelease[0]) >= 10 &&
Number(osRelease[2]) >= 10586
) {
return Number(osRelease[2]) >= 14931 ? 3 : 2;
}
return 1;
}
if ('CI' in env) {
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
return 1;
}
return min;
}
if ('TEAMCITY_VERSION' in env) {
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
}
if (env.COLORTERM === 'truecolor') {
return 3;
}
if ('TERM_PROGRAM' in env) {
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
switch (env.TERM_PROGRAM) {
case 'iTerm.app':
return version >= 3 ? 3 : 2;
case 'Apple_Terminal':
return 2;
// No default
}
}
if (/-256(color)?$/i.test(env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1;
}
if ('COLORTERM' in env) {
return 1;
}
return min;
}
function getSupportLevel(stream) {
const level = supportsColor(stream, stream && stream.isTTY);
return translateLevel(level);
}
module.exports = {
supportsColor: getSupportLevel,
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
};

View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,53 @@
{
"name": "supports-color",
"version": "7.2.0",
"description": "Detect whether a terminal supports color",
"license": "MIT",
"repository": "chalk/supports-color",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js",
"browser.js"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"ansi",
"styles",
"tty",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"support",
"supports",
"capability",
"detect",
"truecolor",
"16m"
],
"dependencies": {
"has-flag": "^4.0.0"
},
"devDependencies": {
"ava": "^1.4.1",
"import-fresh": "^3.0.0",
"xo": "^0.24.0"
},
"browser": "browser.js"
}

View File

@@ -0,0 +1,76 @@
# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color)
> Detect whether a terminal supports color
## Install
```
$ npm install supports-color
```
## Usage
```js
const supportsColor = require('supports-color');
if (supportsColor.stdout) {
console.log('Terminal stdout supports color');
}
if (supportsColor.stdout.has256) {
console.log('Terminal stdout supports 256 colors');
}
if (supportsColor.stderr.has16m) {
console.log('Terminal stderr supports 16 million colors (truecolor)');
}
```
## API
Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
- `.level = 2` and `.has256 = true`: 256 color support
- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
## Info
It obeys the `--color` and `--no-color` CLI flags.
For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
## Related
- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-supports-color?utm_source=npm-supports-color&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
---

68
node_modules/cypress/node_modules/chalk/package.json generated vendored Normal file
View File

@@ -0,0 +1,68 @@
{
"name": "chalk",
"version": "4.1.2",
"description": "Terminal string styling done right",
"license": "MIT",
"repository": "chalk/chalk",
"funding": "https://github.com/chalk/chalk?sponsor=1",
"main": "source",
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && nyc ava && tsd",
"bench": "matcha benchmark.js"
},
"files": [
"source",
"index.d.ts"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"str",
"ansi",
"style",
"styles",
"tty",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"devDependencies": {
"ava": "^2.4.0",
"coveralls": "^3.0.7",
"execa": "^4.0.0",
"import-fresh": "^3.1.0",
"matcha": "^0.7.0",
"nyc": "^15.0.0",
"resolve-from": "^5.0.0",
"tsd": "^0.7.4",
"xo": "^0.28.2"
},
"xo": {
"rules": {
"unicorn/prefer-string-slice": "off",
"unicorn/prefer-includes": "off",
"@typescript-eslint/member-ordering": "off",
"no-redeclare": "off",
"unicorn/string-content": "off",
"unicorn/better-regex": "off"
}
}
}

341
node_modules/cypress/node_modules/chalk/readme.md generated vendored Normal file
View File

@@ -0,0 +1,341 @@
<h1 align="center">
<br>
<br>
<img width="320" src="media/logo.svg" alt="Chalk">
<br>
<br>
<br>
</h1>
> Terminal string styling done right
[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg) [![run on repl.it](https://repl.it/badge/github/chalk/chalk)](https://repl.it/github/chalk/chalk)
<img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
<br>
---
<div align="center">
<p>
<p>
<sup>
Sindre Sorhus' open source work is supported by the community on <a href="https://github.com/sponsors/sindresorhus">GitHub Sponsors</a> and <a href="https://stakes.social/0x44d871aebF0126Bf646753E2C976Aa7e68A66c15">Dev</a>
</sup>
</p>
<sup>Special thanks to:</sup>
<br>
<br>
<a href="https://standardresume.co/tech">
<img src="https://sindresorhus.com/assets/thanks/standard-resume-logo.svg" width="160"/>
</a>
<br>
<br>
<a href="https://retool.com/?utm_campaign=sindresorhus">
<img src="https://sindresorhus.com/assets/thanks/retool-logo.svg" width="230"/>
</a>
<br>
<br>
<a href="https://doppler.com/?utm_campaign=github_repo&utm_medium=referral&utm_content=chalk&utm_source=github">
<div>
<img src="https://dashboard.doppler.com/imgs/logo-long.svg" width="240" alt="Doppler">
</div>
<b>All your environment variables, in one place</b>
<div>
<span>Stop struggling with scattered API keys, hacking together home-brewed tools,</span>
<br>
<span>and avoiding access controls. Keep your team and servers in sync with Doppler.</span>
</div>
</a>
<br>
<a href="https://uibakery.io/?utm_source=chalk&utm_medium=sponsor&utm_campaign=github">
<div>
<img src="https://sindresorhus.com/assets/thanks/uibakery-logo.jpg" width="270" alt="UI Bakery">
</div>
</a>
</p>
</div>
---
<br>
## Highlights
- Expressive API
- Highly performant
- Ability to nest styles
- [256/Truecolor color support](#256-and-truecolor-color-support)
- Auto-detects color support
- Doesn't extend `String.prototype`
- Clean and focused
- Actively maintained
- [Used by ~50,000 packages](https://www.npmjs.com/browse/depended/chalk) as of January 1, 2020
## Install
```console
$ npm install chalk
```
## Usage
```js
const chalk = require('chalk');
console.log(chalk.blue('Hello world!'));
```
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
```js
const chalk = require('chalk');
const log = console.log;
// Combine styled and normal strings
log(chalk.blue('Hello') + ' World' + chalk.red('!'));
// Compose multiple styles using the chainable API
log(chalk.blue.bgRed.bold('Hello world!'));
// Pass in multiple arguments
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
// Nest styles
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
// Nest styles of the same type even (color, underline, background)
log(chalk.green(
'I am a green line ' +
chalk.blue.underline.bold('with a blue substring') +
' that becomes green again!'
));
// ES2015 template literal
log(`
CPU: ${chalk.red('90%')}
RAM: ${chalk.green('40%')}
DISK: ${chalk.yellow('70%')}
`);
// ES2015 tagged template literal
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
// Use RGB colors in terminal emulators that support it.
log(chalk.keyword('orange')('Yay for orange colored text!'));
log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
log(chalk.hex('#DEADED').bold('Bold gray!'));
```
Easily define your own themes:
```js
const chalk = require('chalk');
const error = chalk.bold.red;
const warning = chalk.keyword('orange');
console.log(error('Error!'));
console.log(warning('Warning!'));
```
Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
```js
const name = 'Sindre';
console.log(chalk.green('Hello %s'), name);
//=> 'Hello Sindre'
```
## API
### chalk.`<style>[.<style>...](string, [string...])`
Example: `chalk.red.bold.underline('Hello', 'world');`
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
Multiple arguments will be separated by space.
### chalk.level
Specifies the level of color support.
Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
If you need to change this in a reusable module, create a new instance:
```js
const ctx = new chalk.Instance({level: 0});
```
| Level | Description |
| :---: | :--- |
| `0` | All colors disabled |
| `1` | Basic color support (16 colors) |
| `2` | 256 color support |
| `3` | Truecolor support (16 million colors) |
### chalk.supportsColor
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
### chalk.stderr and chalk.stderr.supportsColor
`chalk.stderr` contains a separate instance configured with color support detected for `stderr` stream instead of `stdout`. Override rules from `chalk.supportsColor` apply to this too. `chalk.stderr.supportsColor` is exposed for convenience.
## Styles
### Modifiers
- `reset` - Resets the current color chain.
- `bold` - Make text bold.
- `dim` - Emitting only a small amount of light.
- `italic` - Make text italic. *(Not widely supported)*
- `underline` - Make text underline. *(Not widely supported)*
- `inverse`- Inverse background and foreground colors.
- `hidden` - Prints the text, but makes it invisible.
- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
- `visible`- Prints the text only when Chalk has a color level > 0. Can be useful for things that are purely cosmetic.
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Tagged template literal
Chalk can be used as a [tagged template literal](https://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
```js
const chalk = require('chalk');
const miles = 18;
const calculateFeet = miles => miles * 5280;
console.log(chalk`
There are {bold 5280 feet} in a mile.
In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
`);
```
Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
Template styles are chained exactly like normal Chalk styles. The following three statements are equivalent:
```js
console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
console.log(chalk.bold.rgb(10, 100, 200)`Hello!`);
console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
```
Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain spaces between parameters.
All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
## 256 and Truecolor color support
Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
Examples:
- `chalk.hex('#DEADED').underline('Hello, world!')`
- `chalk.keyword('orange')('Some orange text')`
- `chalk.rgb(15, 100, 204).inverse('Hello!')`
Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `keyword` for foreground colors and `bgKeyword` for background colors).
- `chalk.bgHex('#DEADED').underline('Hello, world!')`
- `chalk.bgKeyword('orange')('Some orange text')`
- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
The following color models can be used:
- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
- [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
- [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
- [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
- [`ansi`](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) - Example: `chalk.ansi(31).bgAnsi(93)('red on yellowBright')`
- [`ansi256`](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) - Example: `chalk.bgAnsi256(194)('Honeydew, more or less')`
## Windows
If you're on Windows, do yourself a favor and use [Windows Terminal](https://github.com/microsoft/terminal) instead of `cmd.exe`.
## Origin story
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
## chalk for enterprise
Available as part of the Tidelift Subscription.
The maintainers of chalk and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## Related
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)

229
node_modules/cypress/node_modules/chalk/source/index.js generated vendored Normal file
View File

@@ -0,0 +1,229 @@
'use strict';
const ansiStyles = require('ansi-styles');
const {stdout: stdoutColor, stderr: stderrColor} = require('supports-color');
const {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
} = require('./util');
const {isArray} = Array;
// `supportsColor.level` → `ansiStyles.color[name]` mapping
const levelMapping = [
'ansi',
'ansi',
'ansi256',
'ansi16m'
];
const styles = Object.create(null);
const applyOptions = (object, options = {}) => {
if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
throw new Error('The `level` option should be an integer from 0 to 3');
}
// Detect level if not set manually
const colorLevel = stdoutColor ? stdoutColor.level : 0;
object.level = options.level === undefined ? colorLevel : options.level;
};
class ChalkClass {
constructor(options) {
// eslint-disable-next-line no-constructor-return
return chalkFactory(options);
}
}
const chalkFactory = options => {
const chalk = {};
applyOptions(chalk, options);
chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
Object.setPrototypeOf(chalk, Chalk.prototype);
Object.setPrototypeOf(chalk.template, chalk);
chalk.template.constructor = () => {
throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
};
chalk.template.Instance = ChalkClass;
return chalk.template;
};
function Chalk(options) {
return chalkFactory(options);
}
for (const [styleName, style] of Object.entries(ansiStyles)) {
styles[styleName] = {
get() {
const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
Object.defineProperty(this, styleName, {value: builder});
return builder;
}
};
}
styles.visible = {
get() {
const builder = createBuilder(this, this._styler, true);
Object.defineProperty(this, 'visible', {value: builder});
return builder;
}
};
const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256'];
for (const model of usedModels) {
styles[model] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
return createBuilder(this, styler, this._isEmpty);
};
}
};
}
for (const model of usedModels) {
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
styles[bgModel] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
return createBuilder(this, styler, this._isEmpty);
};
}
};
}
const proto = Object.defineProperties(() => {}, {
...styles,
level: {
enumerable: true,
get() {
return this._generator.level;
},
set(level) {
this._generator.level = level;
}
}
});
const createStyler = (open, close, parent) => {
let openAll;
let closeAll;
if (parent === undefined) {
openAll = open;
closeAll = close;
} else {
openAll = parent.openAll + open;
closeAll = close + parent.closeAll;
}
return {
open,
close,
openAll,
closeAll,
parent
};
};
const createBuilder = (self, _styler, _isEmpty) => {
const builder = (...arguments_) => {
if (isArray(arguments_[0]) && isArray(arguments_[0].raw)) {
// Called as a template literal, for example: chalk.red`2 + 3 = {bold ${2+3}}`
return applyStyle(builder, chalkTag(builder, ...arguments_));
}
// Single argument is hot path, implicit coercion is faster than anything
// eslint-disable-next-line no-implicit-coercion
return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
};
// We alter the prototype because we must return a function, but there is
// no way to create a function with a different prototype
Object.setPrototypeOf(builder, proto);
builder._generator = self;
builder._styler = _styler;
builder._isEmpty = _isEmpty;
return builder;
};
const applyStyle = (self, string) => {
if (self.level <= 0 || !string) {
return self._isEmpty ? '' : string;
}
let styler = self._styler;
if (styler === undefined) {
return string;
}
const {openAll, closeAll} = styler;
if (string.indexOf('\u001B') !== -1) {
while (styler !== undefined) {
// Replace any instances already present with a re-opening code
// otherwise only the part of the string until said closing code
// will be colored, and the rest will simply be 'plain'.
string = stringReplaceAll(string, styler.close, styler.open);
styler = styler.parent;
}
}
// We can move both next actions out of loop, because remaining actions in loop won't have
// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
const lfIndex = string.indexOf('\n');
if (lfIndex !== -1) {
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
}
return openAll + string + closeAll;
};
let template;
const chalkTag = (chalk, ...strings) => {
const [firstString] = strings;
if (!isArray(firstString) || !isArray(firstString.raw)) {
// If chalk() was called by itself or with a string,
// return the string itself as a string.
return strings.join(' ');
}
const arguments_ = strings.slice(1);
const parts = [firstString.raw[0]];
for (let i = 1; i < firstString.length; i++) {
parts.push(
String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
String(firstString.raw[i])
);
}
if (template === undefined) {
template = require('./templates');
}
return template(chalk, parts.join(''));
};
Object.defineProperties(Chalk.prototype, styles);
const chalk = Chalk(); // eslint-disable-line new-cap
chalk.supportsColor = stdoutColor;
chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap
chalk.stderr.supportsColor = stderrColor;
module.exports = chalk;

View File

@@ -0,0 +1,134 @@
'use strict';
const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi;
const ESCAPES = new Map([
['n', '\n'],
['r', '\r'],
['t', '\t'],
['b', '\b'],
['f', '\f'],
['v', '\v'],
['0', '\0'],
['\\', '\\'],
['e', '\u001B'],
['a', '\u0007']
]);
function unescape(c) {
const u = c[0] === 'u';
const bracket = c[1] === '{';
if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
return String.fromCharCode(parseInt(c.slice(1), 16));
}
if (u && bracket) {
return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
}
return ESCAPES.get(c) || c;
}
function parseArguments(name, arguments_) {
const results = [];
const chunks = arguments_.trim().split(/\s*,\s*/g);
let matches;
for (const chunk of chunks) {
const number = Number(chunk);
if (!Number.isNaN(number)) {
results.push(number);
} else if ((matches = chunk.match(STRING_REGEX))) {
results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
} else {
throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
}
}
return results;
}
function parseStyle(style) {
STYLE_REGEX.lastIndex = 0;
const results = [];
let matches;
while ((matches = STYLE_REGEX.exec(style)) !== null) {
const name = matches[1];
if (matches[2]) {
const args = parseArguments(name, matches[2]);
results.push([name].concat(args));
} else {
results.push([name]);
}
}
return results;
}
function buildStyle(chalk, styles) {
const enabled = {};
for (const layer of styles) {
for (const style of layer.styles) {
enabled[style[0]] = layer.inverse ? null : style.slice(1);
}
}
let current = chalk;
for (const [styleName, styles] of Object.entries(enabled)) {
if (!Array.isArray(styles)) {
continue;
}
if (!(styleName in current)) {
throw new Error(`Unknown Chalk style: ${styleName}`);
}
current = styles.length > 0 ? current[styleName](...styles) : current[styleName];
}
return current;
}
module.exports = (chalk, temporary) => {
const styles = [];
const chunks = [];
let chunk = [];
// eslint-disable-next-line max-params
temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
if (escapeCharacter) {
chunk.push(unescape(escapeCharacter));
} else if (style) {
const string = chunk.join('');
chunk = [];
chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string));
styles.push({inverse, styles: parseStyle(style)});
} else if (close) {
if (styles.length === 0) {
throw new Error('Found extraneous } in Chalk template literal');
}
chunks.push(buildStyle(chalk, styles)(chunk.join('')));
chunk = [];
styles.pop();
} else {
chunk.push(character);
}
});
chunks.push(chunk.join(''));
if (styles.length > 0) {
const errMessage = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
throw new Error(errMessage);
}
return chunks.join('');
};

39
node_modules/cypress/node_modules/chalk/source/util.js generated vendored Normal file
View File

@@ -0,0 +1,39 @@
'use strict';
const stringReplaceAll = (string, substring, replacer) => {
let index = string.indexOf(substring);
if (index === -1) {
return string;
}
const substringLength = substring.length;
let endIndex = 0;
let returnValue = '';
do {
returnValue += string.substr(endIndex, index - endIndex) + substring + replacer;
endIndex = index + substringLength;
index = string.indexOf(substring, endIndex);
} while (index !== -1);
returnValue += string.substr(endIndex);
return returnValue;
};
const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
let endIndex = 0;
let returnValue = '';
do {
const gotCR = string[index - 1] === '\r';
returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
endIndex = index + 1;
index = string.indexOf('\n', endIndex);
} while (index !== -1);
returnValue += string.substr(endIndex);
return returnValue;
};
module.exports = {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
};

View File

@@ -0,0 +1,54 @@
# 1.0.0 - 2016-01-07
- Removed: unused speed test
- Added: Automatic routing between previously unsupported conversions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `convert()` class
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: all functions to lookup dictionary
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: `ansi` to `ansi256`
([#27](https://github.com/Qix-/color-convert/pull/27))
- Fixed: argument grouping for functions requiring only one argument
([#27](https://github.com/Qix-/color-convert/pull/27))
# 0.6.0 - 2015-07-23
- Added: methods to handle
[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
- rgb2ansi16
- rgb2ansi
- hsl2ansi16
- hsl2ansi
- hsv2ansi16
- hsv2ansi
- hwb2ansi16
- hwb2ansi
- cmyk2ansi16
- cmyk2ansi
- keyword2ansi16
- keyword2ansi
- ansi162rgb
- ansi162hsl
- ansi162hsv
- ansi162hwb
- ansi162cmyk
- ansi162keyword
- ansi2rgb
- ansi2hsl
- ansi2hsv
- ansi2hwb
- ansi2cmyk
- ansi2keyword
([#18](https://github.com/harthur/color-convert/pull/18))
# 0.5.3 - 2015-06-02
- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
([#15](https://github.com/harthur/color-convert/issues/15))
---
Check out commit logs for older releases

View File

@@ -0,0 +1,21 @@
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,68 @@
# color-convert
[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert)
Color-convert is a color conversion library for JavaScript and node.
It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
```js
var convert = require('color-convert');
convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
convert.keyword.rgb('blue'); // [0, 0, 255]
var rgbChannels = convert.rgb.channels; // 3
var cmykChannels = convert.cmyk.channels; // 4
var ansiChannels = convert.ansi16.channels; // 1
```
# Install
```console
$ npm install color-convert
```
# API
Simply get the property of the _from_ and _to_ conversion that you're looking for.
All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
```js
var convert = require('color-convert');
// Hex to LAB
convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
// RGB to CMYK
convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
```
### Arrays
All functions that accept multiple arguments also support passing an array.
Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
```js
var convert = require('color-convert');
convert.rgb.hex(123, 45, 67); // '7B2D43'
convert.rgb.hex([123, 45, 67]); // '7B2D43'
```
## Routing
Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
# Contribute
If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
# License
Copyright &copy; 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).

View File

@@ -0,0 +1,839 @@
/* MIT license */
/* eslint-disable no-mixed-operators */
const cssKeywords = require('color-name');
// NOTE: conversions should only return primitive values (i.e. arrays, or
// values that give correct `typeof` results).
// do not use box values types (i.e. Number(), String(), etc.)
const reverseKeywords = {};
for (const key of Object.keys(cssKeywords)) {
reverseKeywords[cssKeywords[key]] = key;
}
const convert = {
rgb: {channels: 3, labels: 'rgb'},
hsl: {channels: 3, labels: 'hsl'},
hsv: {channels: 3, labels: 'hsv'},
hwb: {channels: 3, labels: 'hwb'},
cmyk: {channels: 4, labels: 'cmyk'},
xyz: {channels: 3, labels: 'xyz'},
lab: {channels: 3, labels: 'lab'},
lch: {channels: 3, labels: 'lch'},
hex: {channels: 1, labels: ['hex']},
keyword: {channels: 1, labels: ['keyword']},
ansi16: {channels: 1, labels: ['ansi16']},
ansi256: {channels: 1, labels: ['ansi256']},
hcg: {channels: 3, labels: ['h', 'c', 'g']},
apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
gray: {channels: 1, labels: ['gray']}
};
module.exports = convert;
// Hide .channels and .labels properties
for (const model of Object.keys(convert)) {
if (!('channels' in convert[model])) {
throw new Error('missing channels property: ' + model);
}
if (!('labels' in convert[model])) {
throw new Error('missing channel labels property: ' + model);
}
if (convert[model].labels.length !== convert[model].channels) {
throw new Error('channel and label counts mismatch: ' + model);
}
const {channels, labels} = convert[model];
delete convert[model].channels;
delete convert[model].labels;
Object.defineProperty(convert[model], 'channels', {value: channels});
Object.defineProperty(convert[model], 'labels', {value: labels});
}
convert.rgb.hsl = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const min = Math.min(r, g, b);
const max = Math.max(r, g, b);
const delta = max - min;
let h;
let s;
if (max === min) {
h = 0;
} else if (r === max) {
h = (g - b) / delta;
} else if (g === max) {
h = 2 + (b - r) / delta;
} else if (b === max) {
h = 4 + (r - g) / delta;
}
h = Math.min(h * 60, 360);
if (h < 0) {
h += 360;
}
const l = (min + max) / 2;
if (max === min) {
s = 0;
} else if (l <= 0.5) {
s = delta / (max + min);
} else {
s = delta / (2 - max - min);
}
return [h, s * 100, l * 100];
};
convert.rgb.hsv = function (rgb) {
let rdif;
let gdif;
let bdif;
let h;
let s;
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const v = Math.max(r, g, b);
const diff = v - Math.min(r, g, b);
const diffc = function (c) {
return (v - c) / 6 / diff + 1 / 2;
};
if (diff === 0) {
h = 0;
s = 0;
} else {
s = diff / v;
rdif = diffc(r);
gdif = diffc(g);
bdif = diffc(b);
if (r === v) {
h = bdif - gdif;
} else if (g === v) {
h = (1 / 3) + rdif - bdif;
} else if (b === v) {
h = (2 / 3) + gdif - rdif;
}
if (h < 0) {
h += 1;
} else if (h > 1) {
h -= 1;
}
}
return [
h * 360,
s * 100,
v * 100
];
};
convert.rgb.hwb = function (rgb) {
const r = rgb[0];
const g = rgb[1];
let b = rgb[2];
const h = convert.rgb.hsl(rgb)[0];
const w = 1 / 255 * Math.min(r, Math.min(g, b));
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
return [h, w * 100, b * 100];
};
convert.rgb.cmyk = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const k = Math.min(1 - r, 1 - g, 1 - b);
const c = (1 - r - k) / (1 - k) || 0;
const m = (1 - g - k) / (1 - k) || 0;
const y = (1 - b - k) / (1 - k) || 0;
return [c * 100, m * 100, y * 100, k * 100];
};
function comparativeDistance(x, y) {
/*
See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
*/
return (
((x[0] - y[0]) ** 2) +
((x[1] - y[1]) ** 2) +
((x[2] - y[2]) ** 2)
);
}
convert.rgb.keyword = function (rgb) {
const reversed = reverseKeywords[rgb];
if (reversed) {
return reversed;
}
let currentClosestDistance = Infinity;
let currentClosestKeyword;
for (const keyword of Object.keys(cssKeywords)) {
const value = cssKeywords[keyword];
// Compute comparative distance
const distance = comparativeDistance(rgb, value);
// Check if its less, if so set as closest
if (distance < currentClosestDistance) {
currentClosestDistance = distance;
currentClosestKeyword = keyword;
}
}
return currentClosestKeyword;
};
convert.keyword.rgb = function (keyword) {
return cssKeywords[keyword];
};
convert.rgb.xyz = function (rgb) {
let r = rgb[0] / 255;
let g = rgb[1] / 255;
let b = rgb[2] / 255;
// Assume sRGB
r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);
const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
return [x * 100, y * 100, z * 100];
};
convert.rgb.lab = function (rgb) {
const xyz = convert.rgb.xyz(rgb);
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
const l = (116 * y) - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.hsl.rgb = function (hsl) {
const h = hsl[0] / 360;
const s = hsl[1] / 100;
const l = hsl[2] / 100;
let t2;
let t3;
let val;
if (s === 0) {
val = l * 255;
return [val, val, val];
}
if (l < 0.5) {
t2 = l * (1 + s);
} else {
t2 = l + s - l * s;
}
const t1 = 2 * l - t2;
const rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) {
t3 = h + 1 / 3 * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
}
if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
val = t2;
} else if (3 * t3 < 2) {
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
} else {
val = t1;
}
rgb[i] = val * 255;
}
return rgb;
};
convert.hsl.hsv = function (hsl) {
const h = hsl[0];
let s = hsl[1] / 100;
let l = hsl[2] / 100;
let smin = s;
const lmin = Math.max(l, 0.01);
l *= 2;
s *= (l <= 1) ? l : 2 - l;
smin *= lmin <= 1 ? lmin : 2 - lmin;
const v = (l + s) / 2;
const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
return [h, sv * 100, v * 100];
};
convert.hsv.rgb = function (hsv) {
const h = hsv[0] / 60;
const s = hsv[1] / 100;
let v = hsv[2] / 100;
const hi = Math.floor(h) % 6;
const f = h - Math.floor(h);
const p = 255 * v * (1 - s);
const q = 255 * v * (1 - (s * f));
const t = 255 * v * (1 - (s * (1 - f)));
v *= 255;
switch (hi) {
case 0:
return [v, t, p];
case 1:
return [q, v, p];
case 2:
return [p, v, t];
case 3:
return [p, q, v];
case 4:
return [t, p, v];
case 5:
return [v, p, q];
}
};
convert.hsv.hsl = function (hsv) {
const h = hsv[0];
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const vmin = Math.max(v, 0.01);
let sl;
let l;
l = (2 - s) * v;
const lmin = (2 - s) * vmin;
sl = s * vmin;
sl /= (lmin <= 1) ? lmin : 2 - lmin;
sl = sl || 0;
l /= 2;
return [h, sl * 100, l * 100];
};
// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
convert.hwb.rgb = function (hwb) {
const h = hwb[0] / 360;
let wh = hwb[1] / 100;
let bl = hwb[2] / 100;
const ratio = wh + bl;
let f;
// Wh + bl cant be > 1
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
}
const i = Math.floor(6 * h);
const v = 1 - bl;
f = 6 * h - i;
if ((i & 0x01) !== 0) {
f = 1 - f;
}
const n = wh + f * (v - wh); // Linear interpolation
let r;
let g;
let b;
/* eslint-disable max-statements-per-line,no-multi-spaces */
switch (i) {
default:
case 6:
case 0: r = v; g = n; b = wh; break;
case 1: r = n; g = v; b = wh; break;
case 2: r = wh; g = v; b = n; break;
case 3: r = wh; g = n; b = v; break;
case 4: r = n; g = wh; b = v; break;
case 5: r = v; g = wh; b = n; break;
}
/* eslint-enable max-statements-per-line,no-multi-spaces */
return [r * 255, g * 255, b * 255];
};
convert.cmyk.rgb = function (cmyk) {
const c = cmyk[0] / 100;
const m = cmyk[1] / 100;
const y = cmyk[2] / 100;
const k = cmyk[3] / 100;
const r = 1 - Math.min(1, c * (1 - k) + k);
const g = 1 - Math.min(1, m * (1 - k) + k);
const b = 1 - Math.min(1, y * (1 - k) + k);
return [r * 255, g * 255, b * 255];
};
convert.xyz.rgb = function (xyz) {
const x = xyz[0] / 100;
const y = xyz[1] / 100;
const z = xyz[2] / 100;
let r;
let g;
let b;
r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
// Assume sRGB
r = r > 0.0031308
? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
: r * 12.92;
g = g > 0.0031308
? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
: g * 12.92;
b = b > 0.0031308
? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
: b * 12.92;
r = Math.min(Math.max(0, r), 1);
g = Math.min(Math.max(0, g), 1);
b = Math.min(Math.max(0, b), 1);
return [r * 255, g * 255, b * 255];
};
convert.xyz.lab = function (xyz) {
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
const l = (116 * y) - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.lab.xyz = function (lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let x;
let y;
let z;
y = (l + 16) / 116;
x = a / 500 + y;
z = y - b / 200;
const y2 = y ** 3;
const x2 = x ** 3;
const z2 = z ** 3;
y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
x *= 95.047;
y *= 100;
z *= 108.883;
return [x, y, z];
};
convert.lab.lch = function (lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let h;
const hr = Math.atan2(b, a);
h = hr * 360 / 2 / Math.PI;
if (h < 0) {
h += 360;
}
const c = Math.sqrt(a * a + b * b);
return [l, c, h];
};
convert.lch.lab = function (lch) {
const l = lch[0];
const c = lch[1];
const h = lch[2];
const hr = h / 360 * 2 * Math.PI;
const a = c * Math.cos(hr);
const b = c * Math.sin(hr);
return [l, a, b];
};
convert.rgb.ansi16 = function (args, saturation = null) {
const [r, g, b] = args;
let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization
value = Math.round(value / 50);
if (value === 0) {
return 30;
}
let ansi = 30
+ ((Math.round(b / 255) << 2)
| (Math.round(g / 255) << 1)
| Math.round(r / 255));
if (value === 2) {
ansi += 60;
}
return ansi;
};
convert.hsv.ansi16 = function (args) {
// Optimization here; we already know the value and don't need to get
// it converted for us.
return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
};
convert.rgb.ansi256 = function (args) {
const r = args[0];
const g = args[1];
const b = args[2];
// We use the extended greyscale palette here, with the exception of
// black and white. normal palette only has 4 greyscale shades.
if (r === g && g === b) {
if (r < 8) {
return 16;
}
if (r > 248) {
return 231;
}
return Math.round(((r - 8) / 247) * 24) + 232;
}
const ansi = 16
+ (36 * Math.round(r / 255 * 5))
+ (6 * Math.round(g / 255 * 5))
+ Math.round(b / 255 * 5);
return ansi;
};
convert.ansi16.rgb = function (args) {
let color = args % 10;
// Handle greyscale
if (color === 0 || color === 7) {
if (args > 50) {
color += 3.5;
}
color = color / 10.5 * 255;
return [color, color, color];
}
const mult = (~~(args > 50) + 1) * 0.5;
const r = ((color & 1) * mult) * 255;
const g = (((color >> 1) & 1) * mult) * 255;
const b = (((color >> 2) & 1) * mult) * 255;
return [r, g, b];
};
convert.ansi256.rgb = function (args) {
// Handle greyscale
if (args >= 232) {
const c = (args - 232) * 10 + 8;
return [c, c, c];
}
args -= 16;
let rem;
const r = Math.floor(args / 36) / 5 * 255;
const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
const b = (rem % 6) / 5 * 255;
return [r, g, b];
};
convert.rgb.hex = function (args) {
const integer = ((Math.round(args[0]) & 0xFF) << 16)
+ ((Math.round(args[1]) & 0xFF) << 8)
+ (Math.round(args[2]) & 0xFF);
const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.hex.rgb = function (args) {
const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
if (!match) {
return [0, 0, 0];
}
let colorString = match[0];
if (match[0].length === 3) {
colorString = colorString.split('').map(char => {
return char + char;
}).join('');
}
const integer = parseInt(colorString, 16);
const r = (integer >> 16) & 0xFF;
const g = (integer >> 8) & 0xFF;
const b = integer & 0xFF;
return [r, g, b];
};
convert.rgb.hcg = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const max = Math.max(Math.max(r, g), b);
const min = Math.min(Math.min(r, g), b);
const chroma = (max - min);
let grayscale;
let hue;
if (chroma < 1) {
grayscale = min / (1 - chroma);
} else {
grayscale = 0;
}
if (chroma <= 0) {
hue = 0;
} else
if (max === r) {
hue = ((g - b) / chroma) % 6;
} else
if (max === g) {
hue = 2 + (b - r) / chroma;
} else {
hue = 4 + (r - g) / chroma;
}
hue /= 6;
hue %= 1;
return [hue * 360, chroma * 100, grayscale * 100];
};
convert.hsl.hcg = function (hsl) {
const s = hsl[1] / 100;
const l = hsl[2] / 100;
const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));
let f = 0;
if (c < 1.0) {
f = (l - 0.5 * c) / (1.0 - c);
}
return [hsl[0], c * 100, f * 100];
};
convert.hsv.hcg = function (hsv) {
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const c = s * v;
let f = 0;
if (c < 1.0) {
f = (v - c) / (1 - c);
}
return [hsv[0], c * 100, f * 100];
};
convert.hcg.rgb = function (hcg) {
const h = hcg[0] / 360;
const c = hcg[1] / 100;
const g = hcg[2] / 100;
if (c === 0.0) {
return [g * 255, g * 255, g * 255];
}
const pure = [0, 0, 0];
const hi = (h % 1) * 6;
const v = hi % 1;
const w = 1 - v;
let mg = 0;
/* eslint-disable max-statements-per-line */
switch (Math.floor(hi)) {
case 0:
pure[0] = 1; pure[1] = v; pure[2] = 0; break;
case 1:
pure[0] = w; pure[1] = 1; pure[2] = 0; break;
case 2:
pure[0] = 0; pure[1] = 1; pure[2] = v; break;
case 3:
pure[0] = 0; pure[1] = w; pure[2] = 1; break;
case 4:
pure[0] = v; pure[1] = 0; pure[2] = 1; break;
default:
pure[0] = 1; pure[1] = 0; pure[2] = w;
}
/* eslint-enable max-statements-per-line */
mg = (1.0 - c) * g;
return [
(c * pure[0] + mg) * 255,
(c * pure[1] + mg) * 255,
(c * pure[2] + mg) * 255
];
};
convert.hcg.hsv = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1.0 - c);
let f = 0;
if (v > 0.0) {
f = c / v;
}
return [hcg[0], f * 100, v * 100];
};
convert.hcg.hsl = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const l = g * (1.0 - c) + 0.5 * c;
let s = 0;
if (l > 0.0 && l < 0.5) {
s = c / (2 * l);
} else
if (l >= 0.5 && l < 1.0) {
s = c / (2 * (1 - l));
}
return [hcg[0], s * 100, l * 100];
};
convert.hcg.hwb = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1.0 - c);
return [hcg[0], (v - c) * 100, (1 - v) * 100];
};
convert.hwb.hcg = function (hwb) {
const w = hwb[1] / 100;
const b = hwb[2] / 100;
const v = 1 - b;
const c = v - w;
let g = 0;
if (c < 1) {
g = (v - c) / (1 - c);
}
return [hwb[0], c * 100, g * 100];
};
convert.apple.rgb = function (apple) {
return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
};
convert.rgb.apple = function (rgb) {
return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
};
convert.gray.rgb = function (args) {
return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
};
convert.gray.hsl = function (args) {
return [0, 0, args[0]];
};
convert.gray.hsv = convert.gray.hsl;
convert.gray.hwb = function (gray) {
return [0, 100, gray[0]];
};
convert.gray.cmyk = function (gray) {
return [0, 0, 0, gray[0]];
};
convert.gray.lab = function (gray) {
return [gray[0], 0, 0];
};
convert.gray.hex = function (gray) {
const val = Math.round(gray[0] / 100 * 255) & 0xFF;
const integer = (val << 16) + (val << 8) + val;
const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.rgb.gray = function (rgb) {
const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
return [val / 255 * 100];
};

View File

@@ -0,0 +1,81 @@
const conversions = require('./conversions');
const route = require('./route');
const convert = {};
const models = Object.keys(conversions);
function wrapRaw(fn) {
const wrappedFn = function (...args) {
const arg0 = args[0];
if (arg0 === undefined || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
return fn(args);
};
// Preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
function wrapRounded(fn) {
const wrappedFn = function (...args) {
const arg0 = args[0];
if (arg0 === undefined || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
const result = fn(args);
// We're assuming the result is an array here.
// see notice in conversions.js; don't use box types
// in conversion functions.
if (typeof result === 'object') {
for (let len = result.length, i = 0; i < len; i++) {
result[i] = Math.round(result[i]);
}
}
return result;
};
// Preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
models.forEach(fromModel => {
convert[fromModel] = {};
Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
const routes = route(fromModel);
const routeModels = Object.keys(routes);
routeModels.forEach(toModel => {
const fn = routes[toModel];
convert[fromModel][toModel] = wrapRounded(fn);
convert[fromModel][toModel].raw = wrapRaw(fn);
});
});
module.exports = convert;

View File

@@ -0,0 +1,48 @@
{
"name": "color-convert",
"description": "Plain color conversion functions",
"version": "2.0.1",
"author": "Heather Arthur <fayearthur@gmail.com>",
"license": "MIT",
"repository": "Qix-/color-convert",
"scripts": {
"pretest": "xo",
"test": "node test/basic.js"
},
"engines": {
"node": ">=7.0.0"
},
"keywords": [
"color",
"colour",
"convert",
"converter",
"conversion",
"rgb",
"hsl",
"hsv",
"hwb",
"cmyk",
"ansi",
"ansi16"
],
"files": [
"index.js",
"conversions.js",
"route.js"
],
"xo": {
"rules": {
"default-case": 0,
"no-inline-comments": 0,
"operator-linebreak": 0
}
},
"devDependencies": {
"chalk": "^2.4.2",
"xo": "^0.24.0"
},
"dependencies": {
"color-name": "~1.1.4"
}
}

View File

@@ -0,0 +1,97 @@
const conversions = require('./conversions');
/*
This function routes a model to all other models.
all functions that are routed have a property `.conversion` attached
to the returned synthetic function. This property is an array
of strings, each with the steps in between the 'from' and 'to'
color models (inclusive).
conversions that are not possible simply are not included.
*/
function buildGraph() {
const graph = {};
// https://jsperf.com/object-keys-vs-for-in-with-closure/3
const models = Object.keys(conversions);
for (let len = models.length, i = 0; i < len; i++) {
graph[models[i]] = {
// http://jsperf.com/1-vs-infinity
// micro-opt, but this is simple.
distance: -1,
parent: null
};
}
return graph;
}
// https://en.wikipedia.org/wiki/Breadth-first_search
function deriveBFS(fromModel) {
const graph = buildGraph();
const queue = [fromModel]; // Unshift -> queue -> pop
graph[fromModel].distance = 0;
while (queue.length) {
const current = queue.pop();
const adjacents = Object.keys(conversions[current]);
for (let len = adjacents.length, i = 0; i < len; i++) {
const adjacent = adjacents[i];
const node = graph[adjacent];
if (node.distance === -1) {
node.distance = graph[current].distance + 1;
node.parent = current;
queue.unshift(adjacent);
}
}
}
return graph;
}
function link(from, to) {
return function (args) {
return to(from(args));
};
}
function wrapConversion(toModel, graph) {
const path = [graph[toModel].parent, toModel];
let fn = conversions[graph[toModel].parent][toModel];
let cur = graph[toModel].parent;
while (graph[cur].parent) {
path.unshift(graph[cur].parent);
fn = link(conversions[graph[cur].parent][cur], fn);
cur = graph[cur].parent;
}
fn.conversion = path;
return fn;
}
module.exports = function (fromModel) {
const graph = deriveBFS(fromModel);
const conversion = {};
const models = Object.keys(graph);
for (let len = models.length, i = 0; i < len; i++) {
const toModel = models[i];
const node = graph[toModel];
if (node.parent === null) {
// No possible conversion, or this node is the source model.
continue;
}
conversion[toModel] = wrapConversion(toModel, graph);
}
return conversion;
};

8
node_modules/cypress/node_modules/color-name/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2015 Dmitry Ivanov
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

11
node_modules/cypress/node_modules/color-name/README.md generated vendored Normal file
View File

@@ -0,0 +1,11 @@
A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/)
```js
var colors = require('color-name');
colors.red //[255,0,0]
```
<a href="LICENSE"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0c/MIT_logo.svg" width="120"/></a>

152
node_modules/cypress/node_modules/color-name/index.js generated vendored Normal file
View File

@@ -0,0 +1,152 @@
'use strict'
module.exports = {
"aliceblue": [240, 248, 255],
"antiquewhite": [250, 235, 215],
"aqua": [0, 255, 255],
"aquamarine": [127, 255, 212],
"azure": [240, 255, 255],
"beige": [245, 245, 220],
"bisque": [255, 228, 196],
"black": [0, 0, 0],
"blanchedalmond": [255, 235, 205],
"blue": [0, 0, 255],
"blueviolet": [138, 43, 226],
"brown": [165, 42, 42],
"burlywood": [222, 184, 135],
"cadetblue": [95, 158, 160],
"chartreuse": [127, 255, 0],
"chocolate": [210, 105, 30],
"coral": [255, 127, 80],
"cornflowerblue": [100, 149, 237],
"cornsilk": [255, 248, 220],
"crimson": [220, 20, 60],
"cyan": [0, 255, 255],
"darkblue": [0, 0, 139],
"darkcyan": [0, 139, 139],
"darkgoldenrod": [184, 134, 11],
"darkgray": [169, 169, 169],
"darkgreen": [0, 100, 0],
"darkgrey": [169, 169, 169],
"darkkhaki": [189, 183, 107],
"darkmagenta": [139, 0, 139],
"darkolivegreen": [85, 107, 47],
"darkorange": [255, 140, 0],
"darkorchid": [153, 50, 204],
"darkred": [139, 0, 0],
"darksalmon": [233, 150, 122],
"darkseagreen": [143, 188, 143],
"darkslateblue": [72, 61, 139],
"darkslategray": [47, 79, 79],
"darkslategrey": [47, 79, 79],
"darkturquoise": [0, 206, 209],
"darkviolet": [148, 0, 211],
"deeppink": [255, 20, 147],
"deepskyblue": [0, 191, 255],
"dimgray": [105, 105, 105],
"dimgrey": [105, 105, 105],
"dodgerblue": [30, 144, 255],
"firebrick": [178, 34, 34],
"floralwhite": [255, 250, 240],
"forestgreen": [34, 139, 34],
"fuchsia": [255, 0, 255],
"gainsboro": [220, 220, 220],
"ghostwhite": [248, 248, 255],
"gold": [255, 215, 0],
"goldenrod": [218, 165, 32],
"gray": [128, 128, 128],
"green": [0, 128, 0],
"greenyellow": [173, 255, 47],
"grey": [128, 128, 128],
"honeydew": [240, 255, 240],
"hotpink": [255, 105, 180],
"indianred": [205, 92, 92],
"indigo": [75, 0, 130],
"ivory": [255, 255, 240],
"khaki": [240, 230, 140],
"lavender": [230, 230, 250],
"lavenderblush": [255, 240, 245],
"lawngreen": [124, 252, 0],
"lemonchiffon": [255, 250, 205],
"lightblue": [173, 216, 230],
"lightcoral": [240, 128, 128],
"lightcyan": [224, 255, 255],
"lightgoldenrodyellow": [250, 250, 210],
"lightgray": [211, 211, 211],
"lightgreen": [144, 238, 144],
"lightgrey": [211, 211, 211],
"lightpink": [255, 182, 193],
"lightsalmon": [255, 160, 122],
"lightseagreen": [32, 178, 170],
"lightskyblue": [135, 206, 250],
"lightslategray": [119, 136, 153],
"lightslategrey": [119, 136, 153],
"lightsteelblue": [176, 196, 222],
"lightyellow": [255, 255, 224],
"lime": [0, 255, 0],
"limegreen": [50, 205, 50],
"linen": [250, 240, 230],
"magenta": [255, 0, 255],
"maroon": [128, 0, 0],
"mediumaquamarine": [102, 205, 170],
"mediumblue": [0, 0, 205],
"mediumorchid": [186, 85, 211],
"mediumpurple": [147, 112, 219],
"mediumseagreen": [60, 179, 113],
"mediumslateblue": [123, 104, 238],
"mediumspringgreen": [0, 250, 154],
"mediumturquoise": [72, 209, 204],
"mediumvioletred": [199, 21, 133],
"midnightblue": [25, 25, 112],
"mintcream": [245, 255, 250],
"mistyrose": [255, 228, 225],
"moccasin": [255, 228, 181],
"navajowhite": [255, 222, 173],
"navy": [0, 0, 128],
"oldlace": [253, 245, 230],
"olive": [128, 128, 0],
"olivedrab": [107, 142, 35],
"orange": [255, 165, 0],
"orangered": [255, 69, 0],
"orchid": [218, 112, 214],
"palegoldenrod": [238, 232, 170],
"palegreen": [152, 251, 152],
"paleturquoise": [175, 238, 238],
"palevioletred": [219, 112, 147],
"papayawhip": [255, 239, 213],
"peachpuff": [255, 218, 185],
"peru": [205, 133, 63],
"pink": [255, 192, 203],
"plum": [221, 160, 221],
"powderblue": [176, 224, 230],
"purple": [128, 0, 128],
"rebeccapurple": [102, 51, 153],
"red": [255, 0, 0],
"rosybrown": [188, 143, 143],
"royalblue": [65, 105, 225],
"saddlebrown": [139, 69, 19],
"salmon": [250, 128, 114],
"sandybrown": [244, 164, 96],
"seagreen": [46, 139, 87],
"seashell": [255, 245, 238],
"sienna": [160, 82, 45],
"silver": [192, 192, 192],
"skyblue": [135, 206, 235],
"slateblue": [106, 90, 205],
"slategray": [112, 128, 144],
"slategrey": [112, 128, 144],
"snow": [255, 250, 250],
"springgreen": [0, 255, 127],
"steelblue": [70, 130, 180],
"tan": [210, 180, 140],
"teal": [0, 128, 128],
"thistle": [216, 191, 216],
"tomato": [255, 99, 71],
"turquoise": [64, 224, 208],
"violet": [238, 130, 238],
"wheat": [245, 222, 179],
"white": [255, 255, 255],
"whitesmoke": [245, 245, 245],
"yellow": [255, 255, 0],
"yellowgreen": [154, 205, 50]
};

View File

@@ -0,0 +1,28 @@
{
"name": "color-name",
"version": "1.1.4",
"description": "A list of color names and its values",
"main": "index.js",
"files": [
"index.js"
],
"scripts": {
"test": "node test.js"
},
"repository": {
"type": "git",
"url": "git@github.com:colorjs/color-name.git"
},
"keywords": [
"color-name",
"color",
"color-keyword",
"keyword"
],
"author": "DY <dfcreative@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/colorjs/color-name/issues"
},
"homepage": "https://github.com/colorjs/color-name"
}

View File

@@ -0,0 +1,361 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). (Format adopted after v3.0.0.)
<!-- markdownlint-disable MD024 -->
<!-- markdownlint-disable MD004 -->
## [6.2.1] (2020-12-13)
### Fixed
- some tests failed if directory path included a space ([1390])
## [6.2.0] (2020-10-25)
### Added
- added 'tsx' file extension for stand-alone executable subcommands ([#1368])
- documented second parameter to `.description()` to describe command arguments ([#1353])
- documentation of special cases with options taking varying numbers of option-arguments ([#1332])
- documentation for terminology ([#1361])
### Fixed
- add missing TypeScript definition for `.addHelpCommand()' ([#1375])
- removed blank line after "Arguments:" in help, to match "Options:" and "Commands:" ([#1360])
### Changed
- update dependencies
## [6.1.0] (2020-08-28)
### Added
- include URL to relevant section of README for error for potential conflict between Command properties and option values ([#1306])
- `.combineFlagAndOptionalValue(false)` to ease upgrade path from older versions of Commander ([#1326])
- allow disabling the built-in help option using `.helpOption(false)` ([#1325])
- allow just some arguments in `argumentDescription` to `.description()` ([#1323])
### Changed
- tidy async test and remove lint override ([#1312])
### Fixed
- executable subcommand launching when script path not known ([#1322])
## [6.0.0] (2020-07-21)
### Added
- add support for variadic options ([#1250])
- allow options to be added with just a short flag ([#1256])
- *Breaking* the option property has same case as flag. e.g. flag `-n` accessed as `opts().n` (previously uppercase)
- *Breaking* throw an error if there might be a clash between option name and a Command property, with advice on how to resolve ([#1275])
### Fixed
- Options which contain -no- in the middle of the option flag should not be treated as negatable. ([#1301])
## [6.0.0-0] (2020-06-20)
(Released in 6.0.0)
## [5.1.0] (2020-04-25)
### Added
- support for multiple command aliases, the first of which is shown in the auto-generated help ([#531], [#1236])
- configuration support in `addCommand()` for `hidden` and `isDefault` ([#1232])
### Fixed
- omit masked help flags from the displayed help ([#645], [#1247])
- remove old short help flag when change help flags using `helpOption` ([#1248])
### Changed
- remove use of `arguments` to improve auto-generated help in editors ([#1235])
- rename `.command()` configuration `noHelp` to `hidden` (but not remove old support) ([#1232])
- improvements to documentation
- update dependencies
- update tested versions of node
- eliminate lint errors in TypeScript ([#1208])
## [5.0.0] (2020-03-14)
### Added
* support for nested commands with action-handlers ([#1] [#764] [#1149])
* `.addCommand()` for adding a separately configured command ([#764] [#1149])
* allow a non-executable to be set as the default command ([#742] [#1149])
* implicit help command when there are subcommands (previously only if executables) ([#1149])
* customise implicit help command with `.addHelpCommand()` ([#1149])
* display error message for unknown subcommand, by default ([#432] [#1088] [#1149])
* display help for missing subcommand, by default ([#1088] [#1149])
* combined short options as single argument may include boolean flags and value flag and value (e.g. `-a -b -p 80` can be written as `-abp80`) ([#1145])
* `.parseOption()` includes short flag and long flag expansions ([#1145])
* `.helpInformation()` returns help text as a string, previously a private routine ([#1169])
* `.parse()` implicitly uses `process.argv` if arguments not specified ([#1172])
* optionally specify where `.parse()` arguments "from", if not following node conventions ([#512] [#1172])
* suggest help option along with unknown command error ([#1179])
* TypeScript definition for `commands` property of `Command` ([#1184])
* export `program` property ([#1195])
* `createCommand` factory method to simplify subclassing ([#1191])
### Fixed
* preserve argument order in subcommands ([#508] [#962] [#1138])
* do not emit `command:*` for executable subcommands ([#809] [#1149])
* action handler called whether or not there are non-option arguments ([#1062] [#1149])
* combining option short flag and value in single argument now works for subcommands ([#1145])
* only add implicit help command when it will not conflict with other uses of argument ([#1153] [#1149])
* implicit help command works with command aliases ([#948] [#1149])
* options are validated whether or not there is an action handler ([#1149])
### Changed
* *Breaking* `.args` contains command arguments with just recognised options removed ([#1032] [#1138])
* *Breaking* display error if required argument for command is missing ([#995] [#1149])
* tighten TypeScript definition of custom option processing function passed to `.option()` ([#1119])
* *Breaking* `.allowUnknownOption()` ([#802] [#1138])
* unknown options included in arguments passed to command action handler
* unknown options included in `.args`
* only recognised option short flags and long flags are expanded (e.g. `-ab` or `--foo=bar`) ([#1145])
* *Breaking* `.parseOptions()` ([#1138])
* `args` in returned result renamed `operands` and does not include anything after first unknown option
* `unknown` in returned result has arguments after first unknown option including operands, not just options and values
* *Breaking* `.on('command:*', callback)` and other command events passed (changed) results from `.parseOptions`, i.e. operands and unknown ([#1138])
* refactor Option from prototype to class ([#1133])
* refactor Command from prototype to class ([#1159])
* changes to error handling ([#1165])
* throw for author error, not just display message
* preflight for variadic error
* add tips to missing subcommand executable
* TypeScript fluent return types changed to be more subclass friendly, return `this` rather than `Command` ([#1180])
* `.parseAsync` returns `Promise<this>` to be consistent with `.parse()` ([#1180])
* update dependencies
### Removed
* removed EventEmitter from TypeScript definition for Command, eliminating implicit peer dependency on `@types/node` ([#1146])
* removed private function `normalize` (the functionality has been integrated into `parseOptions`) ([#1145])
* `parseExpectedArgs` is now private ([#1149])
### Migration Tips
If you use `.on('command:*')` or more complicated tests to detect an unrecognised subcommand, you may be able to delete the code and rely on the default behaviour.
If you use `program.args` or more complicated tests to detect a missing subcommand, you may be able to delete the code and rely on the default behaviour.
If you use `.command('*')` to add a default command, you may be be able to switch to `isDefault:true` with a named command.
If you want to continue combining short options with optional values as though they were boolean flags, set `combineFlagAndOptionalValue(false)`
to expand `-fb` to `-f -b` rather than `-f b`.
## [5.0.0-4] (2020-03-03)
(Released in 5.0.0)
## [5.0.0-3] (2020-02-20)
(Released in 5.0.0)
## [5.0.0-2] (2020-02-10)
(Released in 5.0.0)
## [5.0.0-1] (2020-02-08)
(Released in 5.0.0)
## [5.0.0-0] (2020-02-02)
(Released in 5.0.0)
## [4.1.1] (2020-02-02)
### Fixed
* TypeScript definition for `.action()` should include Promise for async ([#1157])
## [4.1.0] (2020-01-06)
### Added
* two routines to change how option values are handled, and eliminate name clashes with command properties ([#933] [#1102])
* see storeOptionsAsProperties and passCommandToAction in README
* `.parseAsync` to use instead of `.parse` if supply async action handlers ([#806] [#1118])
### Fixed
* Remove trailing blanks from wrapped help text ([#1096])
### Changed
* update dependencies
* extend security coverage for Commander 2.x to 2020-02-03
* improvements to README
* improvements to TypeScript definition documentation
* move old versions out of main CHANGELOG
* removed explicit use of `ts-node` in tests
## [4.0.1] (2019-11-12)
### Fixed
* display help when requested, even if there are missing required options ([#1091])
## [4.0.0] (2019-11-02)
### Added
* automatically wrap and indent help descriptions for options and commands ([#1051])
* `.exitOverride()` allows override of calls to `process.exit` for additional error handling and to keep program running ([#1040])
* support for declaring required options with `.requiredOptions()` ([#1071])
* GitHub Actions support ([#1027])
* translation links in README
### Changed
* dev: switch tests from Sinon+Should to Jest with major rewrite of tests ([#1035])
* call default subcommand even when there are unknown options ([#1047])
* *Breaking* Commander is only officially supported on Node 8 and above, and requires Node 6 ([#1053])
### Fixed
* *Breaking* keep command object out of program.args when action handler called ([#1048])
* also, action handler now passed array of unknown arguments
* complain about unknown options when program argument supplied and action handler ([#1049])
* this changes parameters to `command:*` event to include unknown arguments
* removed deprecated `customFds` option from call to `child_process.spawn` ([#1052])
* rework TypeScript declarations to bring all types into imported namespace ([#1081])
### Migration Tips
#### Testing for no arguments
If you were previously using code like:
```js
if (!program.args.length) ...
```
a partial replacement is:
```js
if (program.rawArgs.length < 3) ...
```
## [4.0.0-1] Prerelease (2019-10-08)
(Released in 4.0.0)
## [4.0.0-0] Prerelease (2019-10-01)
(Released in 4.0.0)
## Older versions
* [3.x](./changelogs/CHANGELOG-3.md)
* [2.x](./changelogs/CHANGELOG-2.md)
* [1.x](./changelogs/CHANGELOG-1.md)
* [0.x](./changelogs/CHANGELOG-0.md)
[#1]: https://github.com/tj/commander.js/issues/1
[#432]: https://github.com/tj/commander.js/issues/432
[#508]: https://github.com/tj/commander.js/issues/508
[#512]: https://github.com/tj/commander.js/issues/512
[#531]: https://github.com/tj/commander.js/issues/531
[#645]: https://github.com/tj/commander.js/issues/645
[#742]: https://github.com/tj/commander.js/issues/742
[#764]: https://github.com/tj/commander.js/issues/764
[#802]: https://github.com/tj/commander.js/issues/802
[#806]: https://github.com/tj/commander.js/issues/806
[#809]: https://github.com/tj/commander.js/issues/809
[#948]: https://github.com/tj/commander.js/issues/948
[#962]: https://github.com/tj/commander.js/issues/962
[#995]: https://github.com/tj/commander.js/issues/995
[#1027]: https://github.com/tj/commander.js/pull/1027
[#1032]: https://github.com/tj/commander.js/issues/1032
[#1035]: https://github.com/tj/commander.js/pull/1035
[#1040]: https://github.com/tj/commander.js/pull/1040
[#1047]: https://github.com/tj/commander.js/pull/1047
[#1048]: https://github.com/tj/commander.js/pull/1048
[#1049]: https://github.com/tj/commander.js/pull/1049
[#1051]: https://github.com/tj/commander.js/pull/1051
[#1052]: https://github.com/tj/commander.js/pull/1052
[#1053]: https://github.com/tj/commander.js/pull/1053
[#1062]: https://github.com/tj/commander.js/pull/1062
[#1071]: https://github.com/tj/commander.js/pull/1071
[#1081]: https://github.com/tj/commander.js/pull/1081
[#1088]: https://github.com/tj/commander.js/issues/1088
[#1091]: https://github.com/tj/commander.js/pull/1091
[#1096]: https://github.com/tj/commander.js/pull/1096
[#1102]: https://github.com/tj/commander.js/pull/1102
[#1118]: https://github.com/tj/commander.js/pull/1118
[#1119]: https://github.com/tj/commander.js/pull/1119
[#1133]: https://github.com/tj/commander.js/pull/1133
[#1138]: https://github.com/tj/commander.js/pull/1138
[#1145]: https://github.com/tj/commander.js/pull/1145
[#1146]: https://github.com/tj/commander.js/pull/1146
[#1149]: https://github.com/tj/commander.js/pull/1149
[#1153]: https://github.com/tj/commander.js/issues/1153
[#1157]: https://github.com/tj/commander.js/pull/1157
[#1159]: https://github.com/tj/commander.js/pull/1159
[#1165]: https://github.com/tj/commander.js/pull/1165
[#1169]: https://github.com/tj/commander.js/pull/1169
[#1172]: https://github.com/tj/commander.js/pull/1172
[#1179]: https://github.com/tj/commander.js/pull/1179
[#1180]: https://github.com/tj/commander.js/pull/1180
[#1184]: https://github.com/tj/commander.js/pull/1184
[#1191]: https://github.com/tj/commander.js/pull/1191
[#1195]: https://github.com/tj/commander.js/pull/1195
[#1208]: https://github.com/tj/commander.js/pull/1208
[#1232]: https://github.com/tj/commander.js/pull/1232
[#1235]: https://github.com/tj/commander.js/pull/1235
[#1236]: https://github.com/tj/commander.js/pull/1236
[#1247]: https://github.com/tj/commander.js/pull/1247
[#1248]: https://github.com/tj/commander.js/pull/1248
[#1250]: https://github.com/tj/commander.js/pull/1250
[#1256]: https://github.com/tj/commander.js/pull/1256
[#1275]: https://github.com/tj/commander.js/pull/1275
[#1301]: https://github.com/tj/commander.js/issues/1301
[#1306]: https://github.com/tj/commander.js/pull/1306
[#1312]: https://github.com/tj/commander.js/pull/1312
[#1322]: https://github.com/tj/commander.js/pull/1322
[#1323]: https://github.com/tj/commander.js/pull/1323
[#1325]: https://github.com/tj/commander.js/pull/1325
[#1326]: https://github.com/tj/commander.js/pull/1326
[#1332]: https://github.com/tj/commander.js/pull/1332
[#1353]: https://github.com/tj/commander.js/pull/1353
[#1360]: https://github.com/tj/commander.js/pull/1360
[#1361]: https://github.com/tj/commander.js/pull/1361
[#1368]: https://github.com/tj/commander.js/pull/1368
[#1375]: https://github.com/tj/commander.js/pull/1375
[#1390]: https://github.com/tj/commander.js/pull/1390
[Unreleased]: https://github.com/tj/commander.js/compare/master...develop
[6.2.1]: https://github.com/tj/commander.js/compare/v6.2.0..v6.2.1
[6.2.0]: https://github.com/tj/commander.js/compare/v6.1.0..v6.2.0
[6.1.0]: https://github.com/tj/commander.js/compare/v6.0.0..v6.1.0
[6.0.0]: https://github.com/tj/commander.js/compare/v5.1.0..v6.0.0
[6.0.0-0]: https://github.com/tj/commander.js/compare/v5.1.0..v6.0.0-0
[5.1.0]: https://github.com/tj/commander.js/compare/v5.0.0..v5.1.0
[5.0.0]: https://github.com/tj/commander.js/compare/v4.1.1..v5.0.0
[5.0.0-4]: https://github.com/tj/commander.js/compare/v5.0.0-3..v5.0.0-4
[5.0.0-3]: https://github.com/tj/commander.js/compare/v5.0.0-2..v5.0.0-3
[5.0.0-2]: https://github.com/tj/commander.js/compare/v5.0.0-1..v5.0.0-2
[5.0.0-1]: https://github.com/tj/commander.js/compare/v5.0.0-0..v5.0.0-1
[5.0.0-0]: https://github.com/tj/commander.js/compare/v4.1.1..v5.0.0-0
[4.1.1]: https://github.com/tj/commander.js/compare/v4.1.0..v4.1.1
[4.1.0]: https://github.com/tj/commander.js/compare/v4.0.1..v4.1.0
[4.0.1]: https://github.com/tj/commander.js/compare/v4.0.0..v4.0.1
[4.0.0]: https://github.com/tj/commander.js/compare/v3.0.2..v4.0.0
[4.0.0-1]: https://github.com/tj/commander.js/compare/v4.0.0-0..v4.0.0-1
[4.0.0-0]: https://github.com/tj/commander.js/compare/v3.0.2...v4.0.0-0

22
node_modules/cypress/node_modules/commander/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,22 @@
(The MIT License)
Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
'Software'), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

791
node_modules/cypress/node_modules/commander/Readme.md generated vendored Normal file
View File

@@ -0,0 +1,791 @@
# Commander.js
[![Build Status](https://api.travis-ci.org/tj/commander.js.svg?branch=master)](http://travis-ci.org/tj/commander.js)
[![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
[![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://npmcharts.com/compare/commander?minimal=true)
[![Install Size](https://packagephobia.now.sh/badge?p=commander)](https://packagephobia.now.sh/result?p=commander)
The complete solution for [node.js](http://nodejs.org) command-line interfaces.
Read this in other languages: English | [简体中文](./Readme_zh-CN.md)
- [Commander.js](#commanderjs)
- [Installation](#installation)
- [Declaring _program_ variable](#declaring-program-variable)
- [Options](#options)
- [Common option types, boolean and value](#common-option-types-boolean-and-value)
- [Default option value](#default-option-value)
- [Other option types, negatable boolean and boolean|value](#other-option-types-negatable-boolean-and-booleanvalue)
- [Custom option processing](#custom-option-processing)
- [Required option](#required-option)
- [Variadic option](#variadic-option)
- [Version option](#version-option)
- [Commands](#commands)
- [Specify the argument syntax](#specify-the-argument-syntax)
- [Action handler (sub)commands](#action-handler-subcommands)
- [Stand-alone executable (sub)commands](#stand-alone-executable-subcommands)
- [Automated help](#automated-help)
- [Custom help](#custom-help)
- [.usage and .name](#usage-and-name)
- [.help(cb)](#helpcb)
- [.outputHelp(cb)](#outputhelpcb)
- [.helpInformation()](#helpinformation)
- [.helpOption(flags, description)](#helpoptionflags-description)
- [.addHelpCommand()](#addhelpcommand)
- [Custom event listeners](#custom-event-listeners)
- [Bits and pieces](#bits-and-pieces)
- [.parse() and .parseAsync()](#parse-and-parseasync)
- [Avoiding option name clashes](#avoiding-option-name-clashes)
- [TypeScript](#typescript)
- [createCommand()](#createcommand)
- [Import into ECMAScript Module](#import-into-ecmascript-module)
- [Node options such as `--harmony`](#node-options-such-as---harmony)
- [Debugging stand-alone executable subcommands](#debugging-stand-alone-executable-subcommands)
- [Override exit handling](#override-exit-handling)
- [Examples](#examples)
- [Support](#support)
- [Commander for enterprise](#commander-for-enterprise)
For information about terms used in this document see: [terminology](./docs/terminology.md)
## Installation
```bash
npm install commander
```
## Declaring _program_ variable
Commander exports a global object which is convenient for quick programs.
This is used in the examples in this README for brevity.
```js
const { program } = require('commander');
program.version('0.0.1');
```
For larger programs which may use commander in multiple ways, including unit testing, it is better to create a local Command object to use.
```js
const { Command } = require('commander');
const program = new Command();
program.version('0.0.1');
```
## Options
Options are defined with the `.option()` method, also serving as documentation for the options. Each option can have a short flag (single character) and a long name, separated by a comma or space or vertical bar ('|').
The options can be accessed as properties on the Command object. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc. See also optional new behaviour to [avoid name clashes](#avoiding-option-name-clashes).
Multiple short flags may optionally be combined in a single argument following the dash: boolean flags, followed by a single option taking a value (possibly followed by the value).
For example `-a -b -p 80` may be written as `-ab -p80` or even `-abp80`.
You can use `--` to indicate the end of the options, and any remaining arguments will be used without being interpreted.
Options on the command line are not positional, and can be specified before or after other arguments.
### Common option types, boolean and value
The two most used option types are a boolean option, and an option which takes its value
from the following argument (declared with angle brackets like `--expect <value>`). Both are `undefined` unless specified on command line.
Example file: [options-common.js](./examples/options-common.js)
```js
program
.option('-d, --debug', 'output extra debugging')
.option('-s, --small', 'small pizza size')
.option('-p, --pizza-type <type>', 'flavour of pizza');
program.parse(process.argv);
if (program.debug) console.log(program.opts());
console.log('pizza details:');
if (program.small) console.log('- small pizza size');
if (program.pizzaType) console.log(`- ${program.pizzaType}`);
```
```bash
$ pizza-options -d
{ debug: true, small: undefined, pizzaType: undefined }
pizza details:
$ pizza-options -p
error: option '-p, --pizza-type <type>' argument missing
$ pizza-options -ds -p vegetarian
{ debug: true, small: true, pizzaType: 'vegetarian' }
pizza details:
- small pizza size
- vegetarian
$ pizza-options --pizza-type=cheese
pizza details:
- cheese
```
`program.parse(arguments)` processes the arguments, leaving any args not consumed by the program options in the `program.args` array.
### Default option value
You can specify a default value for an option which takes a value.
Example file: [options-defaults.js](./examples/options-defaults.js)
```js
program
.option('-c, --cheese <type>', 'add the specified type of cheese', 'blue');
program.parse(process.argv);
console.log(`cheese: ${program.cheese}`);
```
```bash
$ pizza-options
cheese: blue
$ pizza-options --cheese stilton
cheese: stilton
```
### Other option types, negatable boolean and boolean|value
You can define a boolean option long name with a leading `no-` to set the option value to false when used.
Defined alone this also makes the option true by default.
If you define `--foo` first, adding `--no-foo` does not change the default value from what it would
otherwise be. You can specify a default boolean value for a boolean option and it can be overridden on command line.
Example file: [options-negatable.js](./examples/options-negatable.js)
```js
program
.option('--no-sauce', 'Remove sauce')
.option('--cheese <flavour>', 'cheese flavour', 'mozzarella')
.option('--no-cheese', 'plain with no cheese')
.parse(process.argv);
const sauceStr = program.sauce ? 'sauce' : 'no sauce';
const cheeseStr = (program.cheese === false) ? 'no cheese' : `${program.cheese} cheese`;
console.log(`You ordered a pizza with ${sauceStr} and ${cheeseStr}`);
```
```bash
$ pizza-options
You ordered a pizza with sauce and mozzarella cheese
$ pizza-options --sauce
error: unknown option '--sauce'
$ pizza-options --cheese=blue
You ordered a pizza with sauce and blue cheese
$ pizza-options --no-sauce --no-cheese
You ordered a pizza with no sauce and no cheese
```
You can specify an option which may be used as a boolean option but may optionally take an option-argument
(declared with square brackets like `--optional [value]`).
Example file: [options-boolean-or-value.js](./examples/options-boolean-or-value.js)
```js
program
.option('-c, --cheese [type]', 'Add cheese with optional type');
program.parse(process.argv);
if (program.cheese === undefined) console.log('no cheese');
else if (program.cheese === true) console.log('add cheese');
else console.log(`add cheese type ${program.cheese}`);
```
```bash
$ pizza-options
no cheese
$ pizza-options --cheese
add cheese
$ pizza-options --cheese mozzarella
add cheese type mozzarella
```
For information about possible ambiguous cases, see [options taking varying arguments](./docs/options-taking-varying-arguments.md).
### Custom option processing
You may specify a function to do custom processing of option-arguments. The callback function receives two parameters,
the user specified option-argument and the previous value for the option. It returns the new value for the option.
This allows you to coerce the option-argument to the desired type, or accumulate values, or do entirely custom processing.
You can optionally specify the default/starting value for the option after the function parameter.
Example file: [options-custom-processing.js](./examples/options-custom-processing.js)
```js
function myParseInt(value, dummyPrevious) {
// parseInt takes a string and an optional radix
return parseInt(value);
}
function increaseVerbosity(dummyValue, previous) {
return previous + 1;
}
function collect(value, previous) {
return previous.concat([value]);
}
function commaSeparatedList(value, dummyPrevious) {
return value.split(',');
}
program
.option('-f, --float <number>', 'float argument', parseFloat)
.option('-i, --integer <number>', 'integer argument', myParseInt)
.option('-v, --verbose', 'verbosity that can be increased', increaseVerbosity, 0)
.option('-c, --collect <value>', 'repeatable value', collect, [])
.option('-l, --list <items>', 'comma separated list', commaSeparatedList)
;
program.parse(process.argv);
if (program.float !== undefined) console.log(`float: ${program.float}`);
if (program.integer !== undefined) console.log(`integer: ${program.integer}`);
if (program.verbose > 0) console.log(`verbosity: ${program.verbose}`);
if (program.collect.length > 0) console.log(program.collect);
if (program.list !== undefined) console.log(program.list);
```
```bash
$ custom -f 1e2
float: 100
$ custom --integer 2
integer: 2
$ custom -v -v -v
verbose: 3
$ custom -c a -c b -c c
[ 'a', 'b', 'c' ]
$ custom --list x,y,z
[ 'x', 'y', 'z' ]
```
### Required option
You may specify a required (mandatory) option using `.requiredOption`. The option must have a value after parsing, usually specified on the command line, or perhaps from a default value (say from environment). The method is otherwise the same as `.option` in format, taking flags and description, and optional default value or custom processing.
Example file: [options-required.js](./examples/options-required.js)
```js
program
.requiredOption('-c, --cheese <type>', 'pizza must have cheese');
program.parse(process.argv);
```
```bash
$ pizza
error: required option '-c, --cheese <type>' not specified
```
### Variadic option
You may make an option variadic by appending `...` to the value placeholder when declaring the option. On the command line you
can then specify multiple option-arguments, and the parsed option value will be an array. The extra arguments
are read until the first argument starting with a dash. The special argument `--` stops option processing entirely. If a value
is specified in the same argument as the option then no further values are read.
Example file: [options-variadic.js](./examples/options-variadic.js)
```js
program
.option('-n, --number <numbers...>', 'specify numbers')
.option('-l, --letter [letters...]', 'specify letters');
program.parse();
console.log('Options: ', program.opts());
console.log('Remaining arguments: ', program.args);
```
```bash
$ collect -n 1 2 3 --letter a b c
Options: { number: [ '1', '2', '3' ], letter: [ 'a', 'b', 'c' ] }
Remaining arguments: []
$ collect --letter=A -n80 operand
Options: { number: [ '80' ], letter: [ 'A' ] }
Remaining arguments: [ 'operand' ]
$ collect --letter -n 1 -n 2 3 -- operand
Options: { number: [ '1', '2', '3' ], letter: true }
Remaining arguments: [ 'operand' ]
```
For information about possible ambiguous cases, see [options taking varying arguments](./docs/options-taking-varying-arguments.md).
### Version option
The optional `version` method adds handling for displaying the command version. The default option flags are `-V` and `--version`, and when present the command prints the version number and exits.
```js
program.version('0.0.1');
```
```bash
$ ./examples/pizza -V
0.0.1
```
You may change the flags and description by passing additional parameters to the `version` method, using
the same syntax for flags as the `option` method.
```js
program.version('0.0.1', '-v, --vers', 'output the current version');
```
## Commands
You can specify (sub)commands using `.command()` or `.addCommand()`. There are two ways these can be implemented: using an action handler attached to the command, or as a stand-alone executable file (described in more detail later). The subcommands may be nested ([example](./examples/nestedCommands.js)).
In the first parameter to `.command()` you specify the command name and any command-arguments. The arguments may be `<required>` or `[optional]`, and the last argument may also be `variadic...`.
You can use `.addCommand()` to add an already configured subcommand to the program.
For example:
```js
// Command implemented using action handler (description is supplied separately to `.command`)
// Returns new command for configuring.
program
.command('clone <source> [destination]')
.description('clone a repository into a newly created directory')
.action((source, destination) => {
console.log('clone command called');
});
// Command implemented using stand-alone executable file (description is second parameter to `.command`)
// Returns `this` for adding more commands.
program
.command('start <service>', 'start named service')
.command('stop [service]', 'stop named service, or all if no name supplied');
// Command prepared separately.
// Returns `this` for adding more commands.
program
.addCommand(build.makeBuildCommand());
```
Configuration options can be passed with the call to `.command()` and `.addCommand()`. Specifying `hidden: true` will
remove the command from the generated help output. Specifying `isDefault: true` will run the subcommand if no other
subcommand is specified ([example](./examples/defaultCommand.js)).
### Specify the argument syntax
You use `.arguments` to specify the expected command-arguments for the top-level command, and for subcommands they are usually
included in the `.command` call. Angled brackets (e.g. `<required>`) indicate required command-arguments.
Square brackets (e.g. `[optional]`) indicate optional command-arguments.
You can optionally describe the arguments in the help by supplying a hash as second parameter to `.description()`.
Example file: [env](./examples/env)
```js
program
.version('0.1.0')
.arguments('<cmd> [env]')
.description('test command', {
cmd: 'command to run',
env: 'environment to run test in'
})
.action(function (cmd, env) {
console.log('command:', cmd);
console.log('environment:', env || 'no environment given');
});
program.parse(process.argv);
```
The last argument of a command can be variadic, and only the last argument. To make an argument variadic you
append `...` to the argument name. For example:
```js
const { program } = require('commander');
program
.version('0.1.0')
.command('rmdir <dir> [otherDirs...]')
.action(function (dir, otherDirs) {
console.log('rmdir %s', dir);
if (otherDirs) {
otherDirs.forEach(function (oDir) {
console.log('rmdir %s', oDir);
});
}
});
program.parse(process.argv);
```
The variadic argument is passed to the action handler as an array.
### Action handler (sub)commands
You can add options to a command that uses an action handler.
The action handler gets passed a parameter for each argument you declared, and one additional argument which is the
command object itself. This command argument has the values for the command-specific options added as properties.
```js
const { program } = require('commander');
program
.command('rm <dir>')
.option('-r, --recursive', 'Remove recursively')
.action(function (dir, cmdObj) {
console.log('remove ' + dir + (cmdObj.recursive ? ' recursively' : ''))
})
program.parse(process.argv)
```
You may supply an `async` action handler, in which case you call `.parseAsync` rather than `.parse`.
```js
async function run() { /* code goes here */ }
async function main() {
program
.command('run')
.action(run);
await program.parseAsync(process.argv);
}
```
A command's options on the command line are validated when the command is used. Any unknown options will be reported as an error.
### Stand-alone executable (sub)commands
When `.command()` is invoked with a description argument, this tells Commander that you're going to use stand-alone executables for subcommands.
Commander will search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-subcommand`, like `pm-install`, `pm-search`.
You can specify a custom name with the `executableFile` configuration option.
You handle the options for an executable (sub)command in the executable, and don't declare them at the top-level.
Example file: [pm](./examples/pm)
```js
program
.version('0.1.0')
.command('install [name]', 'install one or more packages')
.command('search [query]', 'search with optional query')
.command('update', 'update installed packages', { executableFile: 'myUpdateSubCommand' })
.command('list', 'list packages installed', { isDefault: true });
program.parse(process.argv);
```
If the program is designed to be installed globally, make sure the executables have proper modes, like `755`.
## Automated help
The help information is auto-generated based on the information commander already knows about your program. The default
help option is `-h,--help`.
Example file: [pizza](./examples/pizza)
```bash
$ node ./examples/pizza --help
Usage: pizza [options]
An application for pizzas ordering
Options:
-V, --version output the version number
-p, --peppers Add peppers
-c, --cheese <type> Add the specified type of cheese (default: "marble")
-C, --no-cheese You do not want any cheese
-h, --help display help for command
```
A `help` command is added by default if your command has subcommands. It can be used alone, or with a subcommand name to show
further help for the subcommand. These are effectively the same if the `shell` program has implicit help:
```bash
shell help
shell --help
shell help spawn
shell spawn --help
```
### Custom help
You can display extra information by listening for "--help".
Example file: [custom-help](./examples/custom-help)
```js
program
.option('-f, --foo', 'enable some foo');
// must be before .parse()
program.on('--help', () => {
console.log('');
console.log('Example call:');
console.log(' $ custom-help --help');
});
```
Yields the following help output:
```Text
Usage: custom-help [options]
Options:
-f, --foo enable some foo
-h, --help display help for command
Example call:
$ custom-help --help
```
### .usage and .name
These allow you to customise the usage description in the first line of the help. The name is otherwise
deduced from the (full) program arguments. Given:
```js
program
.name("my-command")
.usage("[global options] command")
```
The help will start with:
```Text
Usage: my-command [global options] command
```
### .help(cb)
Output help information and exit immediately. Optional callback cb allows post-processing of help text before it is displayed.
### .outputHelp(cb)
Output help information without exiting.
Optional callback cb allows post-processing of help text before it is displayed.
### .helpInformation()
Get the command help information as a string for processing or displaying yourself. (The text does not include the custom help
from `--help` listeners.)
### .helpOption(flags, description)
Override the default help flags and description. Pass false to disable the built-in help option.
```js
program
.helpOption('-e, --HELP', 'read more information');
```
### .addHelpCommand()
You can explicitly turn on or off the implicit help command with `.addHelpCommand()` and `.addHelpCommand(false)`.
You can both turn on and customise the help command by supplying the name and description:
```js
program.addHelpCommand('assist [command]', 'show assistance');
```
## Custom event listeners
You can execute custom actions by listening to command and option events.
```js
program.on('option:verbose', function () {
process.env.VERBOSE = this.verbose;
});
program.on('command:*', function (operands) {
console.error(`error: unknown command '${operands[0]}'`);
const availableCommands = program.commands.map(cmd => cmd.name());
mySuggestBestMatch(operands[0], availableCommands);
process.exitCode = 1;
});
```
## Bits and pieces
### .parse() and .parseAsync()
The first argument to `.parse` is the array of strings to parse. You may omit the parameter to implicitly use `process.argv`.
If the arguments follow different conventions than node you can pass a `from` option in the second parameter:
- 'node': default, `argv[0]` is the application and `argv[1]` is the script being run, with user parameters after that
- 'electron': `argv[1]` varies depending on whether the electron application is packaged
- 'user': all of the arguments from the user
For example:
```js
program.parse(process.argv); // Explicit, node conventions
program.parse(); // Implicit, and auto-detect electron
program.parse(['-f', 'filename'], { from: 'user' });
```
### Avoiding option name clashes
The original and default behaviour is that the option values are stored
as properties on the program, and the action handler is passed a
command object with the options values stored as properties.
This is very convenient to code, but the downside is possible clashes with
existing properties of Command.
There are two new routines to change the behaviour, and the default behaviour may change in the future:
- `storeOptionsAsProperties`: whether to store option values as properties on command object, or store separately (specify false) and access using `.opts()`
- `passCommandToAction`: whether to pass command to action handler,
or just the options (specify false)
Example file: [storeOptionsAsProperties-action.js](./examples/storeOptionsAsProperties-action.js)
```js
program
.storeOptionsAsProperties(false)
.passCommandToAction(false);
program
.name('my-program-name')
.option('-n,--name <name>');
program
.command('show')
.option('-a,--action <action>')
.action((options) => {
console.log(options.action);
});
program.parse(process.argv);
const programOptions = program.opts();
console.log(programOptions.name);
```
### TypeScript
The Commander package includes its TypeScript Definition file.
If you use `ts-node` and stand-alone executable subcommands written as `.ts` files, you need to call your program through node to get the subcommands called correctly. e.g.
```bash
node -r ts-node/register pm.ts
```
### createCommand()
This factory function creates a new command. It is exported and may be used instead of using `new`, like:
```js
const { createCommand } = require('commander');
const program = createCommand();
```
`createCommand` is also a method of the Command object, and creates a new command rather than a subcommand. This gets used internally
when creating subcommands using `.command()`, and you may override it to
customise the new subcommand (examples using [subclass](./examples/custom-command-class.js) and [function](./examples/custom-command-function.js)).
### Import into ECMAScript Module
Commander is currently a CommonJS package, and the default export can be imported into an ES Module:
```js
// index.mjs
import commander from 'commander';
const program = commander.program;
const newCommand = new commander.Command();
```
### Node options such as `--harmony`
You can enable `--harmony` option in two ways:
- Use `#! /usr/bin/env node --harmony` in the subcommands scripts. (Note Windows does not support this pattern.)
- Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning subcommand process.
### Debugging stand-alone executable subcommands
An executable subcommand is launched as a separate child process.
If you are using the node inspector for [debugging](https://nodejs.org/en/docs/guides/debugging-getting-started/) executable subcommands using `node --inspect` et al,
the inspector port is incremented by 1 for the spawned subcommand.
If you are using VSCode to debug executable subcommands you need to set the `"autoAttachChildProcesses": true` flag in your launch.json configuration.
### Override exit handling
By default Commander calls `process.exit` when it detects errors, or after displaying the help or version. You can override
this behaviour and optionally supply a callback. The default override throws a `CommanderError`.
The override callback is passed a `CommanderError` with properties `exitCode` number, `code` string, and `message`. The default override behaviour is to throw the error, except for async handling of executable subcommand completion which carries on. The normal display of error messages or version or help
is not affected by the override which is called after the display.
```js
program.exitOverride();
try {
program.parse(process.argv);
} catch (err) {
// custom processing...
}
```
## Examples
Example file: [deploy](./examples/deploy)
```js
const { program } = require('commander');
program
.version('0.1.0')
.option('-C, --chdir <path>', 'change the working directory')
.option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
.option('-T, --no-tests', 'ignore test hook');
program
.command('setup [env]')
.description('run setup commands for all envs')
.option("-s, --setup_mode [mode]", "Which setup mode to use")
.action(function(env, options){
const mode = options.setup_mode || "normal";
env = env || 'all';
console.log('setup for %s env(s) with %s mode', env, mode);
});
program
.command('exec <cmd>')
.alias('ex')
.description('execute the given remote cmd')
.option("-e, --exec_mode <mode>", "Which exec mode to use")
.action(function(cmd, options){
console.log('exec "%s" using %s mode', cmd, options.exec_mode);
}).on('--help', function() {
console.log('');
console.log('Examples:');
console.log('');
console.log(' $ deploy exec sequential');
console.log(' $ deploy exec async');
});
program.parse(process.argv);
```
More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
## Support
The current version of Commander is fully supported on Long Term Support versions of Node, and is likely to work with Node 6 but not tested.
(For versions of Node below Node 6, use Commander 3.x or 2.x.)
The main forum for free and community support is the project [Issues](https://github.com/tj/commander.js/issues) on GitHub.
### Commander for enterprise
Available as part of the Tidelift Subscription
The maintainers of Commander and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-commander?utm_source=npm-commander&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)

1881
node_modules/cypress/node_modules/commander/index.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,51 @@
{
"name": "commander",
"version": "6.2.1",
"description": "the complete solution for node.js command-line programs",
"keywords": [
"commander",
"command",
"option",
"parser",
"cli",
"argument",
"args",
"argv"
],
"author": "TJ Holowaychuk <tj@vision-media.ca>",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/tj/commander.js.git"
},
"scripts": {
"lint": "eslint index.js \"tests/**/*.js\"",
"typescript-lint": "eslint typings/*.ts",
"test": "jest && npm run test-typings",
"test-typings": "tsc -p tsconfig.json"
},
"main": "index",
"files": [
"index.js",
"typings/index.d.ts"
],
"dependencies": {},
"devDependencies": {
"@types/jest": "^26.0.15",
"@types/node": "^14.14.2",
"@typescript-eslint/eslint-plugin": "^4.5.0",
"eslint": "^7.11.0",
"eslint-config-standard-with-typescript": "^19.0.1",
"eslint-plugin-jest": "^24.1.0",
"jest": "^26.6.0",
"standard": "^15.0.0",
"typescript": "^4.0.3"
},
"typings": "typings/index.d.ts",
"jest": {
"collectCoverage": true
},
"engines": {
"node": ">= 6"
}
}

View File

@@ -0,0 +1,410 @@
// Type definitions for commander
// Original definitions by: Alan Agius <https://github.com/alan-agius4>, Marcelo Dezem <https://github.com/mdezem>, vvakame <https://github.com/vvakame>, Jules Randolph <https://github.com/sveinburne>
declare namespace commander {
interface CommanderError extends Error {
code: string;
exitCode: number;
message: string;
nestedError?: string;
}
type CommanderErrorConstructor = new (exitCode: number, code: string, message: string) => CommanderError;
interface Option {
flags: string;
required: boolean; // A value must be supplied when the option is specified.
optional: boolean; // A value is optional when the option is specified.
mandatory: boolean; // The option must have a value after parsing, which usually means it must be specified on command line.
bool: boolean;
short?: string;
long: string;
description: string;
}
type OptionConstructor = new (flags: string, description?: string) => Option;
interface ParseOptions {
from: 'node' | 'electron' | 'user';
}
interface Command {
[key: string]: any; // options as properties
args: string[];
commands: Command[];
/**
* Set the program version to `str`.
*
* This method auto-registers the "-V, --version" flag
* which will print the version number when passed.
*
* You can optionally supply the flags and description to override the defaults.
*/
version(str: string, flags?: string, description?: string): this;
/**
* Define a command, implemented using an action handler.
*
* @remarks
* The command description is supplied using `.description`, not as a parameter to `.command`.
*
* @example
* ```ts
* program
* .command('clone <source> [destination]')
* .description('clone a repository into a newly created directory')
* .action((source, destination) => {
* console.log('clone command called');
* });
* ```
*
* @param nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
* @param opts - configuration options
* @returns new command
*/
command(nameAndArgs: string, opts?: CommandOptions): ReturnType<this['createCommand']>;
/**
* Define a command, implemented in a separate executable file.
*
* @remarks
* The command description is supplied as the second parameter to `.command`.
*
* @example
* ```ts
* program
* .command('start <service>', 'start named service')
* .command('stop [service]', 'stop named service, or all if no name supplied');
* ```
*
* @param nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
* @param description - description of executable command
* @param opts - configuration options
* @returns `this` command for chaining
*/
command(nameAndArgs: string, description: string, opts?: commander.ExecutableCommandOptions): this;
/**
* Factory routine to create a new unattached command.
*
* See .command() for creating an attached subcommand, which uses this routine to
* create the command. You can override createCommand to customise subcommands.
*/
createCommand(name?: string): Command;
/**
* Add a prepared subcommand.
*
* See .command() for creating an attached subcommand which inherits settings from its parent.
*
* @returns `this` command for chaining
*/
addCommand(cmd: Command, opts?: CommandOptions): this;
/**
* Define argument syntax for command.
*
* @returns `this` command for chaining
*/
arguments(desc: string): this;
/**
* Override default decision whether to add implicit help command.
*
* addHelpCommand() // force on
* addHelpCommand(false); // force off
* addHelpCommand('help [cmd]', 'display help for [cmd]'); // force on with custom details
*
* @returns `this` command for chaining
*/
addHelpCommand(enableOrNameAndArgs?: string | boolean, description?: string): this;
/**
* Register callback to use as replacement for calling process.exit.
*/
exitOverride(callback?: (err: CommanderError) => never|void): this;
/**
* Register callback `fn` for the command.
*
* @example
* program
* .command('help')
* .description('display verbose help')
* .action(function() {
* // output help here
* });
*
* @returns `this` command for chaining
*/
action(fn: (...args: any[]) => void | Promise<void>): this;
/**
* Define option with `flags`, `description` and optional
* coercion `fn`.
*
* The `flags` string should contain both the short and long flags,
* separated by comma, a pipe or space. The following are all valid
* all will output this way when `--help` is used.
*
* "-p, --pepper"
* "-p|--pepper"
* "-p --pepper"
*
* @example
* // simple boolean defaulting to false
* program.option('-p, --pepper', 'add pepper');
*
* --pepper
* program.pepper
* // => Boolean
*
* // simple boolean defaulting to true
* program.option('-C, --no-cheese', 'remove cheese');
*
* program.cheese
* // => true
*
* --no-cheese
* program.cheese
* // => false
*
* // required argument
* program.option('-C, --chdir <path>', 'change the working directory');
*
* --chdir /tmp
* program.chdir
* // => "/tmp"
*
* // optional argument
* program.option('-c, --cheese [type]', 'add cheese [marble]');
*
* @returns `this` command for chaining
*/
option(flags: string, description?: string, defaultValue?: string | boolean): this;
option(flags: string, description: string, regexp: RegExp, defaultValue?: string | boolean): this;
option<T>(flags: string, description: string, fn: (value: string, previous: T) => T, defaultValue?: T): this;
/**
* Define a required option, which must have a value after parsing. This usually means
* the option must be specified on the command line. (Otherwise the same as .option().)
*
* The `flags` string should contain both the short and long flags, separated by comma, a pipe or space.
*/
requiredOption(flags: string, description?: string, defaultValue?: string | boolean): this;
requiredOption(flags: string, description: string, regexp: RegExp, defaultValue?: string | boolean): this;
requiredOption<T>(flags: string, description: string, fn: (value: string, previous: T) => T, defaultValue?: T): this;
/**
* Whether to store option values as properties on command object,
* or store separately (specify false). In both cases the option values can be accessed using .opts().
*
* @returns `this` command for chaining
*/
storeOptionsAsProperties(value?: boolean): this;
/**
* Whether to pass command to action handler,
* or just the options (specify false).
*
* @returns `this` command for chaining
*/
passCommandToAction(value?: boolean): this;
/**
* Alter parsing of short flags with optional values.
*
* @example
* // for `.option('-f,--flag [value]'):
* .combineFlagAndOptionalValue(true) // `-f80` is treated like `--flag=80`, this is the default behaviour
* .combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`
*
* @returns `this` command for chaining
*/
combineFlagAndOptionalValue(arg?: boolean): this;
/**
* Allow unknown options on the command line.
*
* @param [arg] if `true` or omitted, no error will be thrown for unknown options.
* @returns `this` command for chaining
*/
allowUnknownOption(arg?: boolean): this;
/**
* Parse `argv`, setting options and invoking commands when defined.
*
* The default expectation is that the arguments are from node and have the application as argv[0]
* and the script being run in argv[1], with user parameters after that.
*
* Examples:
*
* program.parse(process.argv);
* program.parse(); // implicitly use process.argv and auto-detect node vs electron conventions
* program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
*
* @returns `this` command for chaining
*/
parse(argv?: string[], options?: ParseOptions): this;
/**
* Parse `argv`, setting options and invoking commands when defined.
*
* Use parseAsync instead of parse if any of your action handlers are async. Returns a Promise.
*
* The default expectation is that the arguments are from node and have the application as argv[0]
* and the script being run in argv[1], with user parameters after that.
*
* Examples:
*
* program.parseAsync(process.argv);
* program.parseAsync(); // implicitly use process.argv and auto-detect node vs electron conventions
* program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
*
* @returns Promise
*/
parseAsync(argv?: string[], options?: ParseOptions): Promise<this>;
/**
* Parse options from `argv` removing known options,
* and return argv split into operands and unknown arguments.
*
* @example
* argv => operands, unknown
* --known kkk op => [op], []
* op --known kkk => [op], []
* sub --unknown uuu op => [sub], [--unknown uuu op]
* sub -- --unknown uuu op => [sub --unknown uuu op], []
*/
parseOptions(argv: string[]): commander.ParseOptionsResult;
/**
* Return an object containing options as key-value pairs
*/
opts(): { [key: string]: any };
/**
* Set the description.
*
* @returns `this` command for chaining
*/
description(str: string, argsDescription?: {[argName: string]: string}): this;
/**
* Get the description.
*/
description(): string;
/**
* Set an alias for the command.
*
* You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.
*
* @returns `this` command for chaining
*/
alias(alias: string): this;
/**
* Get alias for the command.
*/
alias(): string;
/**
* Set aliases for the command.
*
* Only the first alias is shown in the auto-generated help.
*
* @returns `this` command for chaining
*/
aliases(aliases: string[]): this;
/**
* Get aliases for the command.
*/
aliases(): string[];
/**
* Set the command usage.
*
* @returns `this` command for chaining
*/
usage(str: string): this;
/**
* Get the command usage.
*/
usage(): string;
/**
* Set the name of the command.
*
* @returns `this` command for chaining
*/
name(str: string): this;
/**
* Get the name of the command.
*/
name(): string;
/**
* Output help information for this command.
*
* When listener(s) are available for the helpLongFlag
* those callbacks are invoked.
*/
outputHelp(cb?: (str: string) => string): void;
/**
* Return command help documentation.
*/
helpInformation(): string;
/**
* You can pass in flags and a description to override the help
* flags and help description for your command. Pass in false
* to disable the built-in help option.
*/
helpOption(flags?: string | boolean, description?: string): this;
/**
* Output help information and exit.
*/
help(cb?: (str: string) => string): never;
/**
* Add a listener (callback) for when events occur. (Implemented using EventEmitter.)
*
* @example
* program
* .on('--help', () -> {
* console.log('See web site for more information.');
* });
*/
on(event: string | symbol, listener: (...args: any[]) => void): this;
}
type CommandConstructor = new (name?: string) => Command;
interface CommandOptions {
noHelp?: boolean; // old name for hidden
hidden?: boolean;
isDefault?: boolean;
}
interface ExecutableCommandOptions extends CommandOptions {
executableFile?: string;
}
interface ParseOptionsResult {
operands: string[];
unknown: string[];
}
interface CommanderStatic extends Command {
program: Command;
Command: CommandConstructor;
Option: OptionConstructor;
CommanderError: CommanderErrorConstructor;
}
}
// Declaring namespace AND global
// eslint-disable-next-line @typescript-eslint/no-redeclare
declare const commander: commander.CommanderStatic;
export = commander;

549
node_modules/cypress/node_modules/execa/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,549 @@
/// <reference types="node"/>
import {ChildProcess} from 'child_process';
import {Stream, Readable as ReadableStream} from 'stream';
declare namespace execa {
type StdioOption =
| 'pipe'
| 'ipc'
| 'ignore'
| 'inherit'
| Stream
| number
| undefined;
interface CommonOptions<EncodingType> {
/**
Kill the spawned process when the parent process exits unless either:
- the spawned process is [`detached`](https://nodejs.org/api/child_process.html#child_process_options_detached)
- the parent process is terminated abruptly, for example, with `SIGKILL` as opposed to `SIGTERM` or a normal exit
@default true
*/
readonly cleanup?: boolean;
/**
Prefer locally installed binaries when looking for a binary to execute.
If you `$ npm install foo`, you can then `execa('foo')`.
@default false
*/
readonly preferLocal?: boolean;
/**
Preferred path to find locally installed binaries in (use with `preferLocal`).
@default process.cwd()
*/
readonly localDir?: string;
/**
Path to the Node.js executable to use in child processes.
This can be either an absolute path or a path relative to the `cwd` option.
Requires `preferLocal` to be `true`.
For example, this can be used together with [`get-node`](https://github.com/ehmicky/get-node) to run a specific Node.js version in a child process.
@default process.execPath
*/
readonly execPath?: string;
/**
Buffer the output from the spawned process. When set to `false`, you must read the output of `stdout` and `stderr` (or `all` if the `all` option is `true`). Otherwise the returned promise will not be resolved/rejected.
If the spawned process fails, `error.stdout`, `error.stderr`, and `error.all` will contain the buffered data.
@default true
*/
readonly buffer?: boolean;
/**
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
@default 'pipe'
*/
readonly stdin?: StdioOption;
/**
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
@default 'pipe'
*/
readonly stdout?: StdioOption;
/**
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
@default 'pipe'
*/
readonly stderr?: StdioOption;
/**
Setting this to `false` resolves the promise with the error instead of rejecting it.
@default true
*/
readonly reject?: boolean;
/**
Add an `.all` property on the promise and the resolved value. The property contains the output of the process with `stdout` and `stderr` interleaved.
@default false
*/
readonly all?: boolean;
/**
Strip the final [newline character](https://en.wikipedia.org/wiki/Newline) from the output.
@default true
*/
readonly stripFinalNewline?: boolean;
/**
Set to `false` if you don't want to extend the environment variables when providing the `env` property.
@default true
*/
readonly extendEnv?: boolean;
/**
Current working directory of the child process.
@default process.cwd()
*/
readonly cwd?: string;
/**
Environment key-value pairs. Extends automatically from `process.env`. Set `extendEnv` to `false` if you don't want this.
@default process.env
*/
readonly env?: NodeJS.ProcessEnv;
/**
Explicitly set the value of `argv[0]` sent to the child process. This will be set to `command` or `file` if not specified.
*/
readonly argv0?: string;
/**
Child's [stdio](https://nodejs.org/api/child_process.html#child_process_options_stdio) configuration.
@default 'pipe'
*/
readonly stdio?: 'pipe' | 'ignore' | 'inherit' | readonly StdioOption[];
/**
Specify the kind of serialization used for sending messages between processes when using the `stdio: 'ipc'` option or `execa.node()`:
- `json`: Uses `JSON.stringify()` and `JSON.parse()`.
- `advanced`: Uses [`v8.serialize()`](https://nodejs.org/api/v8.html#v8_v8_serialize_value)
Requires Node.js `13.2.0` or later.
[More info.](https://nodejs.org/api/child_process.html#child_process_advanced_serialization)
@default 'json'
*/
readonly serialization?: 'json' | 'advanced';
/**
Prepare child to run independently of its parent process. Specific behavior [depends on the platform](https://nodejs.org/api/child_process.html#child_process_options_detached).
@default false
*/
readonly detached?: boolean;
/**
Sets the user identity of the process.
*/
readonly uid?: number;
/**
Sets the group identity of the process.
*/
readonly gid?: number;
/**
If `true`, runs `command` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.
We recommend against using this option since it is:
- not cross-platform, encouraging shell-specific syntax.
- slower, because of the additional shell interpretation.
- unsafe, potentially allowing command injection.
@default false
*/
readonly shell?: boolean | string;
/**
Specify the character encoding used to decode the `stdout` and `stderr` output. If set to `null`, then `stdout` and `stderr` will be a `Buffer` instead of a string.
@default 'utf8'
*/
readonly encoding?: EncodingType;
/**
If `timeout` is greater than `0`, the parent will send the signal identified by the `killSignal` property (the default is `SIGTERM`) if the child runs longer than `timeout` milliseconds.
@default 0
*/
readonly timeout?: number;
/**
Largest amount of data in bytes allowed on `stdout` or `stderr`. Default: 100 MB.
@default 100_000_000
*/
readonly maxBuffer?: number;
/**
Signal value to be used when the spawned process will be killed.
@default 'SIGTERM'
*/
readonly killSignal?: string | number;
/**
If `true`, no quoting or escaping of arguments is done on Windows. Ignored on other platforms. This is set to `true` automatically when the `shell` option is `true`.
@default false
*/
readonly windowsVerbatimArguments?: boolean;
/**
On Windows, do not create a new console window. Please note this also prevents `CTRL-C` [from working](https://github.com/nodejs/node/issues/29837) on Windows.
@default true
*/
readonly windowsHide?: boolean;
}
interface Options<EncodingType = string> extends CommonOptions<EncodingType> {
/**
Write some input to the `stdin` of your binary.
*/
readonly input?: string | Buffer | ReadableStream;
}
interface SyncOptions<EncodingType = string> extends CommonOptions<EncodingType> {
/**
Write some input to the `stdin` of your binary.
*/
readonly input?: string | Buffer;
}
interface NodeOptions<EncodingType = string> extends Options<EncodingType> {
/**
The Node.js executable to use.
@default process.execPath
*/
readonly nodePath?: string;
/**
List of [CLI options](https://nodejs.org/api/cli.html#cli_options) passed to the Node.js executable.
@default process.execArgv
*/
readonly nodeOptions?: string[];
}
interface ExecaReturnBase<StdoutStderrType> {
/**
The file and arguments that were run.
*/
command: string;
/**
The numeric exit code of the process that was run.
*/
exitCode: number;
/**
The output of the process on stdout.
*/
stdout: StdoutStderrType;
/**
The output of the process on stderr.
*/
stderr: StdoutStderrType;
/**
Whether the process failed to run.
*/
failed: boolean;
/**
Whether the process timed out.
*/
timedOut: boolean;
/**
Whether the process was killed.
*/
killed: boolean;
/**
The name of the signal that was used to terminate the process. For example, `SIGFPE`.
If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`.
*/
signal?: string;
/**
A human-friendly description of the signal that was used to terminate the process. For example, `Floating point arithmetic error`.
If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`. It is also `undefined` when the signal is very uncommon which should seldomly happen.
*/
signalDescription?: string;
}
interface ExecaSyncReturnValue<StdoutErrorType = string>
extends ExecaReturnBase<StdoutErrorType> {
}
/**
Result of a child process execution. On success this is a plain object. On failure this is also an `Error` instance.
The child process fails when:
- its exit code is not `0`
- it was killed with a signal
- timing out
- being canceled
- there's not enough memory or there are already too many child processes
*/
interface ExecaReturnValue<StdoutErrorType = string>
extends ExecaSyncReturnValue<StdoutErrorType> {
/**
The output of the process with `stdout` and `stderr` interleaved.
This is `undefined` if either:
- the `all` option is `false` (default value)
- `execa.sync()` was used
*/
all?: StdoutErrorType;
/**
Whether the process was canceled.
*/
isCanceled: boolean;
}
interface ExecaSyncError<StdoutErrorType = string>
extends Error,
ExecaReturnBase<StdoutErrorType> {
/**
Error message when the child process failed to run. In addition to the underlying error message, it also contains some information related to why the child process errored.
The child process stderr then stdout are appended to the end, separated with newlines and not interleaved.
*/
message: string;
/**
This is the same as the `message` property except it does not include the child process stdout/stderr.
*/
shortMessage: string;
/**
Original error message. This is the same as the `message` property except it includes neither the child process stdout/stderr nor some additional information added by Execa.
This is `undefined` unless the child process exited due to an `error` event or a timeout.
*/
originalMessage?: string;
}
interface ExecaError<StdoutErrorType = string>
extends ExecaSyncError<StdoutErrorType> {
/**
The output of the process with `stdout` and `stderr` interleaved.
This is `undefined` if either:
- the `all` option is `false` (default value)
- `execa.sync()` was used
*/
all?: StdoutErrorType;
/**
Whether the process was canceled.
*/
isCanceled: boolean;
}
interface KillOptions {
/**
Milliseconds to wait for the child process to terminate before sending `SIGKILL`.
Can be disabled with `false`.
@default 5000
*/
forceKillAfterTimeout?: number | false;
}
interface ExecaChildPromise<StdoutErrorType> {
catch<ResultType = never>(
onRejected?: (reason: ExecaError<StdoutErrorType>) => ResultType | PromiseLike<ResultType>
): Promise<ExecaReturnValue<StdoutErrorType> | ResultType>;
/**
Same as the original [`child_process#kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal), except if `signal` is `SIGTERM` (the default value) and the child process is not terminated after 5 seconds, force it by sending `SIGKILL`.
*/
kill(signal?: string, options?: execa.KillOptions): void;
/**
Similar to [`childProcess.kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal). This is preferred when cancelling the child process execution as the error is more descriptive and [`childProcessResult.isCanceled`](#iscanceled) is set to `true`.
*/
cancel(): void;
/**
Stream combining/interleaving [`stdout`](https://nodejs.org/api/child_process.html#child_process_subprocess_stdout) and [`stderr`](https://nodejs.org/api/child_process.html#child_process_subprocess_stderr).
This is `undefined` if either:
- the `all` option is `false` (the default value)
- both `stdout` and `stderr` options are set to [`'inherit'`, `'ipc'`, `Stream` or `integer`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio)
*/
all?: ReadableStream;
}
type ExecaChildProcess<StdoutErrorType = string> = ChildProcess &
ExecaChildPromise<StdoutErrorType> &
Promise<ExecaReturnValue<StdoutErrorType>>;
}
declare const execa: {
/**
Execute a file.
Think of this as a mix of `child_process.execFile` and `child_process.spawn`.
@param file - The program/script to execute.
@param arguments - Arguments to pass to `file` on execution.
@returns A [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess), which is enhanced to also be a `Promise` for a result `Object` with `stdout` and `stderr` properties.
@example
```
import execa = require('execa');
(async () => {
const {stdout} = await execa('echo', ['unicorns']);
console.log(stdout);
//=> 'unicorns'
// Cancelling a spawned process
const subprocess = execa('node');
setTimeout(() => { spawned.cancel() }, 1000);
try {
await subprocess;
} catch (error) {
console.log(subprocess.killed); // true
console.log(error.isCanceled); // true
}
})();
// Pipe the child process stdout to the current stdout
execa('echo', ['unicorns']).stdout.pipe(process.stdout);
```
*/
(
file: string,
arguments?: readonly string[],
options?: execa.Options
): execa.ExecaChildProcess;
(
file: string,
arguments?: readonly string[],
options?: execa.Options<null>
): execa.ExecaChildProcess<Buffer>;
(file: string, options?: execa.Options): execa.ExecaChildProcess;
(file: string, options?: execa.Options<null>): execa.ExecaChildProcess<
Buffer
>;
/**
Execute a file synchronously.
This method throws an `Error` if the command fails.
@param file - The program/script to execute.
@param arguments - Arguments to pass to `file` on execution.
@returns A result `Object` with `stdout` and `stderr` properties.
*/
sync(
file: string,
arguments?: readonly string[],
options?: execa.SyncOptions
): execa.ExecaSyncReturnValue;
sync(
file: string,
arguments?: readonly string[],
options?: execa.SyncOptions<null>
): execa.ExecaSyncReturnValue<Buffer>;
sync(file: string, options?: execa.SyncOptions): execa.ExecaSyncReturnValue;
sync(
file: string,
options?: execa.SyncOptions<null>
): execa.ExecaSyncReturnValue<Buffer>;
/**
Same as `execa()` except both file and arguments are specified in a single `command` string. For example, `execa('echo', ['unicorns'])` is the same as `execa.command('echo unicorns')`.
If the file or an argument contains spaces, they must be escaped with backslashes. This matters especially if `command` is not a constant but a variable, for example with `__dirname` or `process.cwd()`. Except for spaces, no escaping/quoting is needed.
The `shell` option must be used if the `command` uses shell-specific features, as opposed to being a simple `file` followed by its `arguments`.
@param command - The program/script to execute and its arguments.
@returns A [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess), which is enhanced to also be a `Promise` for a result `Object` with `stdout` and `stderr` properties.
@example
```
import execa = require('execa');
(async () => {
const {stdout} = await execa.command('echo unicorns');
console.log(stdout);
//=> 'unicorns'
})();
```
*/
command(command: string, options?: execa.Options): execa.ExecaChildProcess;
command(command: string, options?: execa.Options<null>): execa.ExecaChildProcess<Buffer>;
/**
Same as `execa.command()` but synchronous.
@param command - The program/script to execute and its arguments.
@returns A result `Object` with `stdout` and `stderr` properties.
*/
commandSync(command: string, options?: execa.SyncOptions): execa.ExecaSyncReturnValue;
commandSync(command: string, options?: execa.SyncOptions<null>): execa.ExecaSyncReturnValue<Buffer>;
/**
Execute a Node.js script as a child process.
Same as `execa('node', [scriptPath, ...arguments], options)` except (like [`child_process#fork()`](https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options)):
- the current Node version and options are used. This can be overridden using the `nodePath` and `nodeArguments` options.
- the `shell` option cannot be used
- an extra channel [`ipc`](https://nodejs.org/api/child_process.html#child_process_options_stdio) is passed to [`stdio`](#stdio)
@param scriptPath - Node.js script to execute.
@param arguments - Arguments to pass to `scriptPath` on execution.
@returns A [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess), which is enhanced to also be a `Promise` for a result `Object` with `stdout` and `stderr` properties.
*/
node(
scriptPath: string,
arguments?: readonly string[],
options?: execa.NodeOptions
): execa.ExecaChildProcess;
node(
scriptPath: string,
arguments?: readonly string[],
options?: execa.Options<null>
): execa.ExecaChildProcess<Buffer>;
node(scriptPath: string, options?: execa.Options): execa.ExecaChildProcess;
node(scriptPath: string, options?: execa.Options<null>): execa.ExecaChildProcess<Buffer>;
};
export = execa;

260
node_modules/cypress/node_modules/execa/index.js generated vendored Normal file
View File

@@ -0,0 +1,260 @@
'use strict';
const path = require('path');
const childProcess = require('child_process');
const crossSpawn = require('cross-spawn');
const stripFinalNewline = require('strip-final-newline');
const npmRunPath = require('npm-run-path');
const onetime = require('onetime');
const makeError = require('./lib/error');
const normalizeStdio = require('./lib/stdio');
const {spawnedKill, spawnedCancel, setupTimeout, setExitHandler} = require('./lib/kill');
const {handleInput, getSpawnedResult, makeAllStream, validateInputSync} = require('./lib/stream.js');
const {mergePromise, getSpawnedPromise} = require('./lib/promise.js');
const {joinCommand, parseCommand} = require('./lib/command.js');
const DEFAULT_MAX_BUFFER = 1000 * 1000 * 100;
const getEnv = ({env: envOption, extendEnv, preferLocal, localDir, execPath}) => {
const env = extendEnv ? {...process.env, ...envOption} : envOption;
if (preferLocal) {
return npmRunPath.env({env, cwd: localDir, execPath});
}
return env;
};
const handleArguments = (file, args, options = {}) => {
const parsed = crossSpawn._parse(file, args, options);
file = parsed.command;
args = parsed.args;
options = parsed.options;
options = {
maxBuffer: DEFAULT_MAX_BUFFER,
buffer: true,
stripFinalNewline: true,
extendEnv: true,
preferLocal: false,
localDir: options.cwd || process.cwd(),
execPath: process.execPath,
encoding: 'utf8',
reject: true,
cleanup: true,
all: false,
windowsHide: true,
...options
};
options.env = getEnv(options);
options.stdio = normalizeStdio(options);
if (process.platform === 'win32' && path.basename(file, '.exe') === 'cmd') {
// #116
args.unshift('/q');
}
return {file, args, options, parsed};
};
const handleOutput = (options, value, error) => {
if (typeof value !== 'string' && !Buffer.isBuffer(value)) {
// When `execa.sync()` errors, we normalize it to '' to mimic `execa()`
return error === undefined ? undefined : '';
}
if (options.stripFinalNewline) {
return stripFinalNewline(value);
}
return value;
};
const execa = (file, args, options) => {
const parsed = handleArguments(file, args, options);
const command = joinCommand(file, args);
let spawned;
try {
spawned = childProcess.spawn(parsed.file, parsed.args, parsed.options);
} catch (error) {
// Ensure the returned error is always both a promise and a child process
const dummySpawned = new childProcess.ChildProcess();
const errorPromise = Promise.reject(makeError({
error,
stdout: '',
stderr: '',
all: '',
command,
parsed,
timedOut: false,
isCanceled: false,
killed: false
}));
return mergePromise(dummySpawned, errorPromise);
}
const spawnedPromise = getSpawnedPromise(spawned);
const timedPromise = setupTimeout(spawned, parsed.options, spawnedPromise);
const processDone = setExitHandler(spawned, parsed.options, timedPromise);
const context = {isCanceled: false};
spawned.kill = spawnedKill.bind(null, spawned.kill.bind(spawned));
spawned.cancel = spawnedCancel.bind(null, spawned, context);
const handlePromise = async () => {
const [{error, exitCode, signal, timedOut}, stdoutResult, stderrResult, allResult] = await getSpawnedResult(spawned, parsed.options, processDone);
const stdout = handleOutput(parsed.options, stdoutResult);
const stderr = handleOutput(parsed.options, stderrResult);
const all = handleOutput(parsed.options, allResult);
if (error || exitCode !== 0 || signal !== null) {
const returnedError = makeError({
error,
exitCode,
signal,
stdout,
stderr,
all,
command,
parsed,
timedOut,
isCanceled: context.isCanceled,
killed: spawned.killed
});
if (!parsed.options.reject) {
return returnedError;
}
throw returnedError;
}
return {
command,
exitCode: 0,
stdout,
stderr,
all,
failed: false,
timedOut: false,
isCanceled: false,
killed: false
};
};
const handlePromiseOnce = onetime(handlePromise);
crossSpawn._enoent.hookChildProcess(spawned, parsed.parsed);
handleInput(spawned, parsed.options.input);
spawned.all = makeAllStream(spawned, parsed.options);
return mergePromise(spawned, handlePromiseOnce);
};
module.exports = execa;
module.exports.sync = (file, args, options) => {
const parsed = handleArguments(file, args, options);
const command = joinCommand(file, args);
validateInputSync(parsed.options);
let result;
try {
result = childProcess.spawnSync(parsed.file, parsed.args, parsed.options);
} catch (error) {
throw makeError({
error,
stdout: '',
stderr: '',
all: '',
command,
parsed,
timedOut: false,
isCanceled: false,
killed: false
});
}
const stdout = handleOutput(parsed.options, result.stdout, result.error);
const stderr = handleOutput(parsed.options, result.stderr, result.error);
if (result.error || result.status !== 0 || result.signal !== null) {
const error = makeError({
stdout,
stderr,
error: result.error,
signal: result.signal,
exitCode: result.status,
command,
parsed,
timedOut: result.error && result.error.code === 'ETIMEDOUT',
isCanceled: false,
killed: result.signal !== null
});
if (!parsed.options.reject) {
return error;
}
throw error;
}
return {
command,
exitCode: 0,
stdout,
stderr,
failed: false,
timedOut: false,
isCanceled: false,
killed: false
};
};
module.exports.command = (command, options) => {
const [file, ...args] = parseCommand(command);
return execa(file, args, options);
};
module.exports.commandSync = (command, options) => {
const [file, ...args] = parseCommand(command);
return execa.sync(file, args, options);
};
module.exports.node = (scriptPath, args, options = {}) => {
if (args && !Array.isArray(args) && typeof args === 'object') {
options = args;
args = [];
}
const stdio = normalizeStdio.node(options);
const defaultExecArgv = process.execArgv.filter(arg => !arg.startsWith('--inspect'));
const {
nodePath = process.execPath,
nodeOptions = defaultExecArgv
} = options;
return execa(
nodePath,
[
...nodeOptions,
scriptPath,
...(Array.isArray(args) ? args : [])
],
{
...options,
stdin: undefined,
stdout: undefined,
stderr: undefined,
stdio,
shell: false
}
);
};

32
node_modules/cypress/node_modules/execa/lib/command.js generated vendored Normal file
View File

@@ -0,0 +1,32 @@
'use strict';
const SPACES_REGEXP = / +/g;
const joinCommand = (file, args = []) => {
if (!Array.isArray(args)) {
return file;
}
return [file, ...args].join(' ');
};
// Handle `execa.command()`
const parseCommand = command => {
const tokens = [];
for (const token of command.trim().split(SPACES_REGEXP)) {
// Allow spaces to be escaped by a backslash if not meant as a delimiter
const previousToken = tokens[tokens.length - 1];
if (previousToken && previousToken.endsWith('\\')) {
// Merge previous token with current one
tokens[tokens.length - 1] = `${previousToken.slice(0, -1)} ${token}`;
} else {
tokens.push(token);
}
}
return tokens;
};
module.exports = {
joinCommand,
parseCommand
};

86
node_modules/cypress/node_modules/execa/lib/error.js generated vendored Normal file
View File

@@ -0,0 +1,86 @@
'use strict';
const {signalsByName} = require('human-signals');
const getErrorPrefix = ({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled}) => {
if (timedOut) {
return `timed out after ${timeout} milliseconds`;
}
if (isCanceled) {
return 'was canceled';
}
if (errorCode !== undefined) {
return `failed with ${errorCode}`;
}
if (signal !== undefined) {
return `was killed with ${signal} (${signalDescription})`;
}
if (exitCode !== undefined) {
return `failed with exit code ${exitCode}`;
}
return 'failed';
};
const makeError = ({
stdout,
stderr,
all,
error,
signal,
exitCode,
command,
timedOut,
isCanceled,
killed,
parsed: {options: {timeout}}
}) => {
// `signal` and `exitCode` emitted on `spawned.on('exit')` event can be `null`.
// We normalize them to `undefined`
exitCode = exitCode === null ? undefined : exitCode;
signal = signal === null ? undefined : signal;
const signalDescription = signal === undefined ? undefined : signalsByName[signal].description;
const errorCode = error && error.code;
const prefix = getErrorPrefix({timedOut, timeout, errorCode, signal, signalDescription, exitCode, isCanceled});
const execaMessage = `Command ${prefix}: ${command}`;
const isError = Object.prototype.toString.call(error) === '[object Error]';
const shortMessage = isError ? `${execaMessage}\n${error.message}` : execaMessage;
const message = [shortMessage, stderr, stdout].filter(Boolean).join('\n');
if (isError) {
error.originalMessage = error.message;
error.message = message;
} else {
error = new Error(message);
}
error.shortMessage = shortMessage;
error.command = command;
error.exitCode = exitCode;
error.signal = signal;
error.signalDescription = signalDescription;
error.stdout = stdout;
error.stderr = stderr;
if (all !== undefined) {
error.all = all;
}
if ('bufferedData' in error) {
delete error.bufferedData;
}
error.failed = true;
error.timedOut = Boolean(timedOut);
error.isCanceled = isCanceled;
error.killed = killed && !timedOut;
return error;
};
module.exports = makeError;

112
node_modules/cypress/node_modules/execa/lib/kill.js generated vendored Normal file
View File

@@ -0,0 +1,112 @@
'use strict';
const os = require('os');
const onExit = require('signal-exit');
const DEFAULT_FORCE_KILL_TIMEOUT = 1000 * 5;
// Monkey-patches `childProcess.kill()` to add `forceKillAfterTimeout` behavior
const spawnedKill = (kill, signal = 'SIGTERM', options = {}) => {
const killResult = kill(signal);
setKillTimeout(kill, signal, options, killResult);
return killResult;
};
const setKillTimeout = (kill, signal, options, killResult) => {
if (!shouldForceKill(signal, options, killResult)) {
return;
}
const timeout = getForceKillAfterTimeout(options);
const t = setTimeout(() => {
kill('SIGKILL');
}, timeout);
// Guarded because there's no `.unref()` when `execa` is used in the renderer
// process in Electron. This cannot be tested since we don't run tests in
// Electron.
// istanbul ignore else
if (t.unref) {
t.unref();
}
};
const shouldForceKill = (signal, {forceKillAfterTimeout}, killResult) => {
return isSigterm(signal) && forceKillAfterTimeout !== false && killResult;
};
const isSigterm = signal => {
return signal === os.constants.signals.SIGTERM ||
(typeof signal === 'string' && signal.toUpperCase() === 'SIGTERM');
};
const getForceKillAfterTimeout = ({forceKillAfterTimeout = true}) => {
if (forceKillAfterTimeout === true) {
return DEFAULT_FORCE_KILL_TIMEOUT;
}
if (!Number.isFinite(forceKillAfterTimeout) || forceKillAfterTimeout < 0) {
throw new TypeError(`Expected the \`forceKillAfterTimeout\` option to be a non-negative integer, got \`${forceKillAfterTimeout}\` (${typeof forceKillAfterTimeout})`);
}
return forceKillAfterTimeout;
};
// `childProcess.cancel()`
const spawnedCancel = (spawned, context) => {
const killResult = spawned.kill();
if (killResult) {
context.isCanceled = true;
}
};
const timeoutKill = (spawned, signal, reject) => {
spawned.kill(signal);
reject(Object.assign(new Error('Timed out'), {timedOut: true, signal}));
};
// `timeout` option handling
const setupTimeout = (spawned, {timeout, killSignal = 'SIGTERM'}, spawnedPromise) => {
if (timeout === 0 || timeout === undefined) {
return spawnedPromise;
}
if (!Number.isFinite(timeout) || timeout < 0) {
throw new TypeError(`Expected the \`timeout\` option to be a non-negative integer, got \`${timeout}\` (${typeof timeout})`);
}
let timeoutId;
const timeoutPromise = new Promise((resolve, reject) => {
timeoutId = setTimeout(() => {
timeoutKill(spawned, killSignal, reject);
}, timeout);
});
const safeSpawnedPromise = spawnedPromise.finally(() => {
clearTimeout(timeoutId);
});
return Promise.race([timeoutPromise, safeSpawnedPromise]);
};
// `cleanup` option handling
const setExitHandler = async (spawned, {cleanup, detached}, timedPromise) => {
if (!cleanup || detached) {
return timedPromise;
}
const removeExitHandler = onExit(() => {
spawned.kill();
});
return timedPromise.finally(() => {
removeExitHandler();
});
};
module.exports = {
spawnedKill,
spawnedCancel,
setupTimeout,
setExitHandler
};

46
node_modules/cypress/node_modules/execa/lib/promise.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
'use strict';
const nativePromisePrototype = (async () => {})().constructor.prototype;
const descriptors = ['then', 'catch', 'finally'].map(property => [
property,
Reflect.getOwnPropertyDescriptor(nativePromisePrototype, property)
]);
// The return value is a mixin of `childProcess` and `Promise`
const mergePromise = (spawned, promise) => {
for (const [property, descriptor] of descriptors) {
// Starting the main `promise` is deferred to avoid consuming streams
const value = typeof promise === 'function' ?
(...args) => Reflect.apply(descriptor.value, promise(), args) :
descriptor.value.bind(promise);
Reflect.defineProperty(spawned, property, {...descriptor, value});
}
return spawned;
};
// Use promises instead of `child_process` events
const getSpawnedPromise = spawned => {
return new Promise((resolve, reject) => {
spawned.on('exit', (exitCode, signal) => {
resolve({exitCode, signal});
});
spawned.on('error', error => {
reject(error);
});
if (spawned.stdin) {
spawned.stdin.on('error', error => {
reject(error);
});
}
});
};
module.exports = {
mergePromise,
getSpawnedPromise
};

52
node_modules/cypress/node_modules/execa/lib/stdio.js generated vendored Normal file
View File

@@ -0,0 +1,52 @@
'use strict';
const aliases = ['stdin', 'stdout', 'stderr'];
const hasAlias = opts => aliases.some(alias => opts[alias] !== undefined);
const normalizeStdio = opts => {
if (!opts) {
return;
}
const {stdio} = opts;
if (stdio === undefined) {
return aliases.map(alias => opts[alias]);
}
if (hasAlias(opts)) {
throw new Error(`It's not possible to provide \`stdio\` in combination with one of ${aliases.map(alias => `\`${alias}\``).join(', ')}`);
}
if (typeof stdio === 'string') {
return stdio;
}
if (!Array.isArray(stdio)) {
throw new TypeError(`Expected \`stdio\` to be of type \`string\` or \`Array\`, got \`${typeof stdio}\``);
}
const length = Math.max(stdio.length, aliases.length);
return Array.from({length}, (value, index) => stdio[index]);
};
module.exports = normalizeStdio;
// `ipc` is pushed unless it is already present
module.exports.node = opts => {
const stdio = normalizeStdio(opts);
if (stdio === 'ipc') {
return 'ipc';
}
if (stdio === undefined || typeof stdio === 'string') {
return [stdio, stdio, stdio, 'ipc'];
}
if (stdio.includes('ipc')) {
return stdio;
}
return [...stdio, 'ipc'];
};

97
node_modules/cypress/node_modules/execa/lib/stream.js generated vendored Normal file
View File

@@ -0,0 +1,97 @@
'use strict';
const isStream = require('is-stream');
const getStream = require('get-stream');
const mergeStream = require('merge-stream');
// `input` option
const handleInput = (spawned, input) => {
// Checking for stdin is workaround for https://github.com/nodejs/node/issues/26852
// TODO: Remove `|| spawned.stdin === undefined` once we drop support for Node.js <=12.2.0
if (input === undefined || spawned.stdin === undefined) {
return;
}
if (isStream(input)) {
input.pipe(spawned.stdin);
} else {
spawned.stdin.end(input);
}
};
// `all` interleaves `stdout` and `stderr`
const makeAllStream = (spawned, {all}) => {
if (!all || (!spawned.stdout && !spawned.stderr)) {
return;
}
const mixed = mergeStream();
if (spawned.stdout) {
mixed.add(spawned.stdout);
}
if (spawned.stderr) {
mixed.add(spawned.stderr);
}
return mixed;
};
// On failure, `result.stdout|stderr|all` should contain the currently buffered stream
const getBufferedData = async (stream, streamPromise) => {
if (!stream) {
return;
}
stream.destroy();
try {
return await streamPromise;
} catch (error) {
return error.bufferedData;
}
};
const getStreamPromise = (stream, {encoding, buffer, maxBuffer}) => {
if (!stream || !buffer) {
return;
}
if (encoding) {
return getStream(stream, {encoding, maxBuffer});
}
return getStream.buffer(stream, {maxBuffer});
};
// Retrieve result of child process: exit code, signal, error, streams (stdout/stderr/all)
const getSpawnedResult = async ({stdout, stderr, all}, {encoding, buffer, maxBuffer}, processDone) => {
const stdoutPromise = getStreamPromise(stdout, {encoding, buffer, maxBuffer});
const stderrPromise = getStreamPromise(stderr, {encoding, buffer, maxBuffer});
const allPromise = getStreamPromise(all, {encoding, buffer, maxBuffer: maxBuffer * 2});
try {
return await Promise.all([processDone, stdoutPromise, stderrPromise, allPromise]);
} catch (error) {
return Promise.all([
{error, signal: error.signal, timedOut: error.timedOut},
getBufferedData(stdout, stdoutPromise),
getBufferedData(stderr, stderrPromise),
getBufferedData(all, allPromise)
]);
}
};
const validateInputSync = ({input}) => {
if (isStream(input)) {
throw new TypeError('The `input` option cannot be a stream in sync mode');
}
};
module.exports = {
handleInput,
makeAllStream,
getSpawnedResult,
validateInputSync
};

9
node_modules/cypress/node_modules/execa/license generated vendored Normal file
View File

@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

71
node_modules/cypress/node_modules/execa/package.json generated vendored Normal file
View File

@@ -0,0 +1,71 @@
{
"name": "execa",
"version": "4.1.0",
"description": "Process execution for humans",
"license": "MIT",
"repository": "sindresorhus/execa",
"funding": "https://github.com/sindresorhus/execa?sponsor=1",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "https://sindresorhus.com"
},
"engines": {
"node": ">=10"
},
"scripts": {
"test": "xo && nyc ava && tsd"
},
"files": [
"index.js",
"index.d.ts",
"lib"
],
"keywords": [
"exec",
"child",
"process",
"execute",
"fork",
"execfile",
"spawn",
"file",
"shell",
"bin",
"binary",
"binaries",
"npm",
"path",
"local"
],
"dependencies": {
"cross-spawn": "^7.0.0",
"get-stream": "^5.0.0",
"human-signals": "^1.1.1",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^4.0.0",
"onetime": "^5.1.0",
"signal-exit": "^3.0.2",
"strip-final-newline": "^2.0.0"
},
"devDependencies": {
"@types/node": "^12.12.18",
"ava": "^2.1.0",
"coveralls": "^3.0.9",
"get-node": "^6.6.0",
"is-running": "^2.1.0",
"nyc": "^14.1.1",
"p-event": "^4.1.0",
"tempfile": "^3.0.0",
"tsd": "^0.11.0",
"xo": "^0.25.3"
},
"nyc": {
"exclude": [
"**/fixtures/**",
"**/test.js",
"**/test/**"
]
}
}

656
node_modules/cypress/node_modules/execa/readme.md generated vendored Normal file
View File

@@ -0,0 +1,656 @@
<img src="media/logo.svg" width="400">
<br>
[![Build Status](https://travis-ci.com/sindresorhus/execa.svg?branch=master)](https://travis-ci.com/github/sindresorhus/execa) [![Coverage Status](https://coveralls.io/repos/github/sindresorhus/execa/badge.svg?branch=master)](https://coveralls.io/github/sindresorhus/execa?branch=master)
> Process execution for humans
---
Netlify is looking for a senior/expert Node.js backend engineer to join a fully remote, international, diverse (44% women and non-binary) and friendly team. This is for the team where one of the co-maintainers [@ehmicky](https://github.com/ehmicky) is working. The job description is [here](https://boards.greenhouse.io/netlify/jobs/4832483002).
---
## Why
This package improves [`child_process`](https://nodejs.org/api/child_process.html) methods with:
- Promise interface.
- [Strips the final newline](#stripfinalnewline) from the output so you don't have to do `stdout.trim()`.
- Supports [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) binaries cross-platform.
- [Improved Windows support.](https://github.com/IndigoUnited/node-cross-spawn#why)
- Higher max buffer. 100 MB instead of 200 KB.
- [Executes locally installed binaries by name.](#preferlocal)
- [Cleans up spawned processes when the parent process dies.](#cleanup)
- [Get interleaved output](#all) from `stdout` and `stderr` similar to what is printed on the terminal. [*(Async only)*](#execasyncfile-arguments-options)
- [Can specify file and arguments as a single string without a shell](#execacommandcommand-options)
- More descriptive errors.
## Install
```
$ npm install execa
```
## Usage
```js
const execa = require('execa');
(async () => {
const {stdout} = await execa('echo', ['unicorns']);
console.log(stdout);
//=> 'unicorns'
})();
```
### Pipe the child process stdout to the parent
```js
const execa = require('execa');
execa('echo', ['unicorns']).stdout.pipe(process.stdout);
```
### Handling Errors
```js
const execa = require('execa');
(async () => {
// Catching an error
try {
await execa('unknown', ['command']);
} catch (error) {
console.log(error);
/*
{
message: 'Command failed with ENOENT: unknown command spawn unknown ENOENT',
errno: -2,
code: 'ENOENT',
syscall: 'spawn unknown',
path: 'unknown',
spawnargs: ['command'],
originalMessage: 'spawn unknown ENOENT',
shortMessage: 'Command failed with ENOENT: unknown command spawn unknown ENOENT',
command: 'unknown command',
stdout: '',
stderr: '',
all: '',
failed: true,
timedOut: false,
isCanceled: false,
killed: false
}
*/
}
})();
```
### Cancelling a spawned process
```js
const execa = require('execa');
(async () => {
const subprocess = execa('node');
setTimeout(() => {
subprocess.cancel();
}, 1000);
try {
await subprocess;
} catch (error) {
console.log(subprocess.killed); // true
console.log(error.isCanceled); // true
}
})()
```
### Catching an error with the sync method
```js
try {
execa.sync('unknown', ['command']);
} catch (error) {
console.log(error);
/*
{
message: 'Command failed with ENOENT: unknown command spawnSync unknown ENOENT',
errno: -2,
code: 'ENOENT',
syscall: 'spawnSync unknown',
path: 'unknown',
spawnargs: ['command'],
originalMessage: 'spawnSync unknown ENOENT',
shortMessage: 'Command failed with ENOENT: unknown command spawnSync unknown ENOENT',
command: 'unknown command',
stdout: '',
stderr: '',
all: '',
failed: true,
timedOut: false,
isCanceled: false,
killed: false
}
*/
}
```
### Kill a process
Using SIGTERM, and after 2 seconds, kill it with SIGKILL.
```js
const subprocess = execa('node');
setTimeout(() => {
subprocess.kill('SIGTERM', {
forceKillAfterTimeout: 2000
});
}, 1000);
```
## API
### execa(file, arguments, options?)
Execute a file. Think of this as a mix of [`child_process.execFile()`](https://nodejs.org/api/child_process.html#child_process_child_process_execfile_file_args_options_callback) and [`child_process.spawn()`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options).
No escaping/quoting is needed.
Unless the [`shell`](#shell) option is used, no shell interpreter (Bash, `cmd.exe`, etc.) is used, so shell features such as variables substitution (`echo $PATH`) are not allowed.
Returns a [`child_process` instance](https://nodejs.org/api/child_process.html#child_process_class_childprocess) which:
- is also a `Promise` resolving or rejecting with a [`childProcessResult`](#childProcessResult).
- exposes the following additional methods and properties.
#### kill(signal?, options?)
Same as the original [`child_process#kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal) except: if `signal` is `SIGTERM` (the default value) and the child process is not terminated after 5 seconds, force it by sending `SIGKILL`.
##### options.forceKillAfterTimeout
Type: `number | false`\
Default: `5000`
Milliseconds to wait for the child process to terminate before sending `SIGKILL`.
Can be disabled with `false`.
#### cancel()
Similar to [`childProcess.kill()`](https://nodejs.org/api/child_process.html#child_process_subprocess_kill_signal). This is preferred when cancelling the child process execution as the error is more descriptive and [`childProcessResult.isCanceled`](#iscanceled) is set to `true`.
#### all
Type: `ReadableStream | undefined`
Stream combining/interleaving [`stdout`](https://nodejs.org/api/child_process.html#child_process_subprocess_stdout) and [`stderr`](https://nodejs.org/api/child_process.html#child_process_subprocess_stderr).
This is `undefined` if either:
- the [`all` option](#all-2) is `false` (the default value)
- both [`stdout`](#stdout-1) and [`stderr`](#stderr-1) options are set to [`'inherit'`, `'ipc'`, `Stream` or `integer`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio)
### execa.sync(file, arguments?, options?)
Execute a file synchronously.
Returns or throws a [`childProcessResult`](#childProcessResult).
### execa.command(command, options?)
Same as [`execa()`](#execafile-arguments-options) except both file and arguments are specified in a single `command` string. For example, `execa('echo', ['unicorns'])` is the same as `execa.command('echo unicorns')`.
If the file or an argument contains spaces, they must be escaped with backslashes. This matters especially if `command` is not a constant but a variable, for example with `__dirname` or `process.cwd()`. Except for spaces, no escaping/quoting is needed.
The [`shell` option](#shell) must be used if the `command` uses shell-specific features, as opposed to being a simple `file` followed by its `arguments`.
### execa.commandSync(command, options?)
Same as [`execa.command()`](#execacommand-command-options) but synchronous.
Returns or throws a [`childProcessResult`](#childProcessResult).
### execa.node(scriptPath, arguments?, options?)
Execute a Node.js script as a child process.
Same as `execa('node', [scriptPath, ...arguments], options)` except (like [`child_process#fork()`](https://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options)):
- the current Node version and options are used. This can be overridden using the [`nodePath`](#nodepath-for-node-only) and [`nodeOptions`](#nodeoptions-for-node-only) options.
- the [`shell`](#shell) option cannot be used
- an extra channel [`ipc`](https://nodejs.org/api/child_process.html#child_process_options_stdio) is passed to [`stdio`](#stdio)
### childProcessResult
Type: `object`
Result of a child process execution. On success this is a plain object. On failure this is also an `Error` instance.
The child process [fails](#failed) when:
- its [exit code](#exitcode) is not `0`
- it was [killed](#killed) with a [signal](#signal)
- [timing out](#timedout)
- [being canceled](#iscanceled)
- there's not enough memory or there are already too many child processes
#### command
Type: `string`
The file and arguments that were run.
#### exitCode
Type: `number`
The numeric exit code of the process that was run.
#### stdout
Type: `string | Buffer`
The output of the process on stdout.
#### stderr
Type: `string | Buffer`
The output of the process on stderr.
#### all
Type: `string | Buffer | undefined`
The output of the process with `stdout` and `stderr` interleaved.
This is `undefined` if either:
- the [`all` option](#all-2) is `false` (the default value)
- `execa.sync()` was used
#### failed
Type: `boolean`
Whether the process failed to run.
#### timedOut
Type: `boolean`
Whether the process timed out.
#### isCanceled
Type: `boolean`
Whether the process was canceled.
#### killed
Type: `boolean`
Whether the process was killed.
#### signal
Type: `string | undefined`
The name of the signal that was used to terminate the process. For example, `SIGFPE`.
If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`.
#### signalDescription
Type: `string | undefined`
A human-friendly description of the signal that was used to terminate the process. For example, `Floating point arithmetic error`.
If a signal terminated the process, this property is defined and included in the error message. Otherwise it is `undefined`. It is also `undefined` when the signal is very uncommon which should seldomly happen.
#### message
Type: `string`
Error message when the child process failed to run. In addition to the [underlying error message](#originalMessage), it also contains some information related to why the child process errored.
The child process [stderr](#stderr) then [stdout](#stdout) are appended to the end, separated with newlines and not interleaved.
#### shortMessage
Type: `string`
This is the same as the [`message` property](#message) except it does not include the child process stdout/stderr.
#### originalMessage
Type: `string | undefined`
Original error message. This is the same as the `message` property except it includes neither the child process stdout/stderr nor some additional information added by Execa.
This is `undefined` unless the child process exited due to an `error` event or a timeout.
### options
Type: `object`
#### cleanup
Type: `boolean`\
Default: `true`
Kill the spawned process when the parent process exits unless either:
- the spawned process is [`detached`](https://nodejs.org/api/child_process.html#child_process_options_detached)
- the parent process is terminated abruptly, for example, with `SIGKILL` as opposed to `SIGTERM` or a normal exit
#### preferLocal
Type: `boolean`\
Default: `false`
Prefer locally installed binaries when looking for a binary to execute.\
If you `$ npm install foo`, you can then `execa('foo')`.
#### localDir
Type: `string`\
Default: `process.cwd()`
Preferred path to find locally installed binaries in (use with `preferLocal`).
#### execPath
Type: `string`\
Default: `process.execPath` (Current Node.js executable)
Path to the Node.js executable to use in child processes.
This can be either an absolute path or a path relative to the [`cwd` option](#cwd).
Requires [`preferLocal`](#preferlocal) to be `true`.
For example, this can be used together with [`get-node`](https://github.com/ehmicky/get-node) to run a specific Node.js version in a child process.
#### buffer
Type: `boolean`\
Default: `true`
Buffer the output from the spawned process. When set to `false`, you must read the output of [`stdout`](#stdout-1) and [`stderr`](#stderr-1) (or [`all`](#all) if the [`all`](#all-2) option is `true`). Otherwise the returned promise will not be resolved/rejected.
If the spawned process fails, [`error.stdout`](#stdout), [`error.stderr`](#stderr), and [`error.all`](#all) will contain the buffered data.
#### input
Type: `string | Buffer | stream.Readable`
Write some input to the `stdin` of your binary.\
Streams are not allowed when using the synchronous methods.
#### stdin
Type: `string | number | Stream | undefined`\
Default: `pipe`
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
#### stdout
Type: `string | number | Stream | undefined`\
Default: `pipe`
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
#### stderr
Type: `string | number | Stream | undefined`\
Default: `pipe`
Same options as [`stdio`](https://nodejs.org/dist/latest-v6.x/docs/api/child_process.html#child_process_options_stdio).
#### all
Type: `boolean`\
Default: `false`
Add an `.all` property on the [promise](#all) and the [resolved value](#all-1). The property contains the output of the process with `stdout` and `stderr` interleaved.
#### reject
Type: `boolean`\
Default: `true`
Setting this to `false` resolves the promise with the error instead of rejecting it.
#### stripFinalNewline
Type: `boolean`\
Default: `true`
Strip the final [newline character](https://en.wikipedia.org/wiki/Newline) from the output.
#### extendEnv
Type: `boolean`\
Default: `true`
Set to `false` if you don't want to extend the environment variables when providing the `env` property.
---
Execa also accepts the below options which are the same as the options for [`child_process#spawn()`](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options)/[`child_process#exec()`](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)
#### cwd
Type: `string`\
Default: `process.cwd()`
Current working directory of the child process.
#### env
Type: `object`\
Default: `process.env`
Environment key-value pairs. Extends automatically from `process.env`. Set [`extendEnv`](#extendenv) to `false` if you don't want this.
#### argv0
Type: `string`
Explicitly set the value of `argv[0]` sent to the child process. This will be set to `file` if not specified.
#### stdio
Type: `string | string[]`\
Default: `pipe`
Child's [stdio](https://nodejs.org/api/child_process.html#child_process_options_stdio) configuration.
#### serialization
Type: `string`\
Default: `'json'`
Specify the kind of serialization used for sending messages between processes when using the [`stdio: 'ipc'`](#stdio) option or [`execa.node()`](#execanodescriptpath-arguments-options):
- `json`: Uses `JSON.stringify()` and `JSON.parse()`.
- `advanced`: Uses [`v8.serialize()`](https://nodejs.org/api/v8.html#v8_v8_serialize_value)
Requires Node.js `13.2.0` or later.
[More info.](https://nodejs.org/api/child_process.html#child_process_advanced_serialization)
#### detached
Type: `boolean`
Prepare child to run independently of its parent process. Specific behavior [depends on the platform](https://nodejs.org/api/child_process.html#child_process_options_detached).
#### uid
Type: `number`
Sets the user identity of the process.
#### gid
Type: `number`
Sets the group identity of the process.
#### shell
Type: `boolean | string`\
Default: `false`
If `true`, runs `file` inside of a shell. Uses `/bin/sh` on UNIX and `cmd.exe` on Windows. A different shell can be specified as a string. The shell should understand the `-c` switch on UNIX or `/d /s /c` on Windows.
We recommend against using this option since it is:
- not cross-platform, encouraging shell-specific syntax.
- slower, because of the additional shell interpretation.
- unsafe, potentially allowing command injection.
#### encoding
Type: `string | null`\
Default: `utf8`
Specify the character encoding used to decode the `stdout` and `stderr` output. If set to `null`, then `stdout` and `stderr` will be a `Buffer` instead of a string.
#### timeout
Type: `number`\
Default: `0`
If timeout is greater than `0`, the parent will send the signal identified by the `killSignal` property (the default is `SIGTERM`) if the child runs longer than timeout milliseconds.
#### maxBuffer
Type: `number`\
Default: `100_000_000` (100 MB)
Largest amount of data in bytes allowed on `stdout` or `stderr`.
#### killSignal
Type: `string | number`\
Default: `SIGTERM`
Signal value to be used when the spawned process will be killed.
#### windowsVerbatimArguments
Type: `boolean`\
Default: `false`
If `true`, no quoting or escaping of arguments is done on Windows. Ignored on other platforms. This is set to `true` automatically when the `shell` option is `true`.
#### windowsHide
Type: `boolean`\
Default: `true`
On Windows, do not create a new console window. Please note this also prevents `CTRL-C` [from working](https://github.com/nodejs/node/issues/29837) on Windows.
#### nodePath *(For `.node()` only)*
Type: `string`\
Default: [`process.execPath`](https://nodejs.org/api/process.html#process_process_execpath)
Node.js executable used to create the child process.
#### nodeOptions *(For `.node()` only)*
Type: `string[]`\
Default: [`process.execArgv`](https://nodejs.org/api/process.html#process_process_execargv)
List of [CLI options](https://nodejs.org/api/cli.html#cli_options) passed to the Node.js executable.
## Tips
### Retry on error
Gracefully handle failures by using automatic retries and exponential backoff with the [`p-retry`](https://github.com/sindresorhus/p-retry) package:
```js
const pRetry = require('p-retry');
const run = async () => {
const results = await execa('curl', ['-sSL', 'https://sindresorhus.com/unicorn']);
return results;
};
(async () => {
console.log(await pRetry(run, {retries: 5}));
})();
```
### Save and pipe output from a child process
Let's say you want to show the output of a child process in real-time while also saving it to a variable.
```js
const execa = require('execa');
const subprocess = execa('echo', ['foo']);
subprocess.stdout.pipe(process.stdout);
(async () => {
const {stdout} = await subprocess;
console.log('child output:', stdout);
})();
```
### Redirect output to a file
```js
const execa = require('execa');
const subprocess = execa('echo', ['foo'])
subprocess.stdout.pipe(fs.createWriteStream('stdout.txt'))
```
### Redirect input from a file
```js
const execa = require('execa');
const subprocess = execa('cat')
fs.createReadStream('stdin.txt').pipe(subprocess.stdin)
```
### Execute the current package's binary
```js
const {getBinPathSync} = require('get-bin-path');
const binPath = getBinPathSync();
const subprocess = execa(binPath);
```
`execa` can be combined with [`get-bin-path`](https://github.com/ehmicky/get-bin-path) to test the current package's binary. As opposed to hard-coding the path to the binary, this validates that the `package.json` `bin` field is correctly set up.
## Related
- [gulp-execa](https://github.com/ehmicky/gulp-execa) - Gulp plugin for `execa`
- [nvexeca](https://github.com/ehmicky/nvexeca) - Run `execa` using any Node.js version
- [sudo-prompt](https://github.com/jorangreef/sudo-prompt) - Run commands with elevated privileges.
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [@ehmicky](https://github.com/ehmicky)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-execa?utm_source=npm-execa&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>

View File

@@ -0,0 +1,52 @@
'use strict';
const {PassThrough: PassThroughStream} = require('stream');
module.exports = options => {
options = {...options};
const {array} = options;
let {encoding} = options;
const isBuffer = encoding === 'buffer';
let objectMode = false;
if (array) {
objectMode = !(encoding || isBuffer);
} else {
encoding = encoding || 'utf8';
}
if (isBuffer) {
encoding = null;
}
const stream = new PassThroughStream({objectMode});
if (encoding) {
stream.setEncoding(encoding);
}
let length = 0;
const chunks = [];
stream.on('data', chunk => {
chunks.push(chunk);
if (objectMode) {
length = chunks.length;
} else {
length += chunk.length;
}
});
stream.getBufferedValue = () => {
if (array) {
return chunks;
}
return isBuffer ? Buffer.concat(chunks, length) : chunks.join('');
};
stream.getBufferedLength = () => length;
return stream;
};

108
node_modules/cypress/node_modules/get-stream/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,108 @@
/// <reference types="node"/>
import {Stream} from 'stream';
declare class MaxBufferErrorClass extends Error {
readonly name: 'MaxBufferError';
constructor();
}
declare namespace getStream {
interface Options {
/**
Maximum length of the returned string. If it exceeds this value before the stream ends, the promise will be rejected with a `MaxBufferError` error.
@default Infinity
*/
readonly maxBuffer?: number;
}
interface OptionsWithEncoding<EncodingType = BufferEncoding> extends Options {
/**
[Encoding](https://nodejs.org/api/buffer.html#buffer_buffer) of the incoming stream.
@default 'utf8'
*/
readonly encoding?: EncodingType;
}
type MaxBufferError = MaxBufferErrorClass;
}
declare const getStream: {
/**
Get the `stream` as a string.
@returns A promise that resolves when the end event fires on the stream, indicating that there is no more data to be read. The stream is switched to flowing mode.
@example
```
import * as fs from 'fs';
import getStream = require('get-stream');
(async () => {
const stream = fs.createReadStream('unicorn.txt');
console.log(await getStream(stream));
// ,,))))))));,
// __)))))))))))))),
// \|/ -\(((((''''((((((((.
// -*-==//////(('' . `)))))),
// /|\ ))| o ;-. '((((( ,(,
// ( `| / ) ;))))' ,_))^;(~
// | | | ,))((((_ _____------~~~-. %,;(;(>';'~
// o_); ; )))(((` ~---~ `:: \ %%~~)(v;(`('~
// ; ''''```` `: `:::|\,__,%% );`'; ~
// | _ ) / `:|`----' `-'
// ______/\/~ | / /
// /~;;.____/;;' / ___--,-( `;;;/
// / // _;______;'------~~~~~ /;;/\ /
// // | | / ; \;;,\
// (<_ | ; /',/-----' _>
// \_| ||_ //~;~~~~~~~~~
// `\_| (,~~
// \~\
// ~~
})();
```
*/
(stream: Stream, options?: getStream.OptionsWithEncoding): Promise<string>;
/**
Get the `stream` as a buffer.
It honors the `maxBuffer` option as above, but it refers to byte length rather than string length.
*/
buffer(
stream: Stream,
options?: getStream.OptionsWithEncoding
): Promise<Buffer>;
/**
Get the `stream` as an array of values.
It honors both the `maxBuffer` and `encoding` options. The behavior changes slightly based on the encoding chosen:
- When `encoding` is unset, it assumes an [object mode stream](https://nodesource.com/blog/understanding-object-streams/) and collects values emitted from `stream` unmodified. In this case `maxBuffer` refers to the number of items in the array (not the sum of their sizes).
- When `encoding` is set to `buffer`, it collects an array of buffers. `maxBuffer` refers to the summed byte lengths of every buffer in the array.
- When `encoding` is set to anything else, it collects an array of strings. `maxBuffer` refers to the summed character lengths of every string in the array.
*/
array<StreamObjectModeType>(
stream: Stream,
options?: getStream.Options
): Promise<StreamObjectModeType[]>;
array(
stream: Stream,
options: getStream.OptionsWithEncoding<'buffer'>
): Promise<Buffer[]>;
array(
stream: Stream,
options: getStream.OptionsWithEncoding<BufferEncoding>
): Promise<string[]>;
MaxBufferError: typeof MaxBufferErrorClass;
// TODO: Remove this for the next major release
default: typeof getStream;
};
export = getStream;

60
node_modules/cypress/node_modules/get-stream/index.js generated vendored Normal file
View File

@@ -0,0 +1,60 @@
'use strict';
const {constants: BufferConstants} = require('buffer');
const pump = require('pump');
const bufferStream = require('./buffer-stream');
class MaxBufferError extends Error {
constructor() {
super('maxBuffer exceeded');
this.name = 'MaxBufferError';
}
}
async function getStream(inputStream, options) {
if (!inputStream) {
return Promise.reject(new Error('Expected a stream'));
}
options = {
maxBuffer: Infinity,
...options
};
const {maxBuffer} = options;
let stream;
await new Promise((resolve, reject) => {
const rejectPromise = error => {
// Don't retrieve an oversized buffer.
if (error && stream.getBufferedLength() <= BufferConstants.MAX_LENGTH) {
error.bufferedData = stream.getBufferedValue();
}
reject(error);
};
stream = pump(inputStream, bufferStream(options), error => {
if (error) {
rejectPromise(error);
return;
}
resolve();
});
stream.on('data', () => {
if (stream.getBufferedLength() > maxBuffer) {
rejectPromise(new MaxBufferError());
}
});
});
return stream.getBufferedValue();
}
module.exports = getStream;
// TODO: Remove this for the next major release
module.exports.default = getStream;
module.exports.buffer = (stream, options) => getStream(stream, {...options, encoding: 'buffer'});
module.exports.array = (stream, options) => getStream(stream, {...options, array: true});
module.exports.MaxBufferError = MaxBufferError;

Some files were not shown because too many files have changed in this diff Show More