This commit is contained in:
Krivega Dmitriy
2023-10-21 11:25:37 +03:00
commit 66e33b7b00
15 changed files with 14714 additions and 0 deletions

46
.gitignore vendored Normal file
View File

@@ -0,0 +1,46 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
node_modules
.pnp
.pnp.js
.yarn
# testing
examples/coverage/coverage/*
.nyc_output
# next.js
.next/
out/
build
dist
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# turbo
.turbo
# Cypress test outputs
**/cypress/videos/
**/cypress/screenshots/
# ENV file
.env
# parcel
.parcel-cache
dist

0
README.md Normal file
View File

1
bin/cli.d.ts vendored Executable file
View File

@@ -0,0 +1 @@
#!/usr/bin/env node

3640
bin/cli.js Executable file

File diff suppressed because it is too large Load Diff

3600
bin/cli.mjs Executable file

File diff suppressed because it is too large Load Diff

346
index.d.ts vendored Normal file
View File

@@ -0,0 +1,346 @@
type TestState = "failed" | "passed" | "pending" | "skipped";
type TestAttemptState = "failed" | "passed" | "pending";
type TestingType$1 = "e2e" | "component";
interface MochaError {
message: string;
name: string;
stack: string;
parsedStack: MochaParsedStackItem[];
codeFrame: MochaCodeFrame;
}
interface MochaInvocationDetails {
function: string;
fileUrl: string;
originalFile: string;
relativeFile: string;
absoluteFile: string;
line: number;
column: number;
whitespace: string;
stack: string;
}
interface MochaCodeFrame {
line: number;
column: number;
originalFile: string;
relativeFile: string;
absoluteFile: string;
frame: string;
language: string;
}
interface MochaParsedStackItem {
message: string;
whitespace: string;
function?: string;
fileUrl?: string;
originalFile?: string;
relativeFile?: string;
absoluteFile?: string;
line?: number;
column?: number;
}
interface MochaHook {
title: string;
hookName: string;
hookId: string;
pending: boolean;
body: string;
type: string;
file: null | string;
invocationDetails: MochaInvocationDetails;
currentRetry: number;
retries: number;
_slow: number;
}
type TimingKey = "before each" | "after each" | "after all" | "before all";
type Timing = {
[key in TimingKey]?: HookTimingItem;
} & {
lifecycle: number;
test: TimingItem;
};
interface HookTimingItem extends TimingItem {
hookId: string;
}
interface TimingItem {
fnDuration: number;
afterFnDuration: number;
}
declare namespace Cypress12 {
namespace SpecAfter {
interface Payload {
error: string | null;
hooks: Hooks[] | null;
reporter?: string;
reporterStats: ReporterStats | null;
screenshots: Screenshot[];
spec: Spec;
stats: Stats;
tests: Test[] | null;
video: string | null;
}
interface Spec {
absolute: string;
baseName: string;
fileExtension: string;
fileName: string;
name: string;
relative: string;
relativeToCommonRoot: string;
specFileExtension: string;
specType: string;
}
interface Screenshot {
height: number;
name: string | null;
path: string;
screenshotId: string;
takenAt: string;
testAttemptIndex: number;
testId: string;
width: number;
}
interface ReporterStats {
suites: number;
tests: number;
passes: number;
pending: number;
failures: number;
start: string;
end: string;
duration: number;
}
interface Stats {
suites: number;
tests: number;
passes: number;
pending: number;
skipped: number;
failures: number;
wallClockStartedAt: string;
wallClockEndedAt: string;
wallClockDuration: number;
}
interface Test {
attempts: TestAttempt[];
body: string;
displayError: string | null;
state: TestState;
title: string[];
testId: string;
}
interface Hooks {
hookId: string;
hookName: "before each" | "after each" | "before all" | "after all";
title: string[];
body: string;
}
interface TestAttempt {
error: TestError | null;
failedFromHookId: string | null;
state: TestAttemptState;
timings: Timing | null;
videoTimestamp: number;
wallClockDuration: number;
wallClockStartedAt: string;
}
interface TestError {
message: string;
name: string;
stack: string;
codeFrame: CodeFrame | null;
}
interface CodeFrame {
line: number | null;
column: number | null;
originalFile: string | null;
relativeFile: string | null;
absoluteFile: string | null;
frame: string | null;
language: string | null;
}
}
namespace TestAfter {
interface Payload extends TestBefore.Payload {
duration: number;
err?: MochaError;
hooks: MochaHook[];
timings: Timing;
}
}
namespace TestBefore {
interface Payload {
async: boolean;
body: string;
currentRetry: number;
fullTitle: string;
hooks?: MochaHook[];
id: string;
invocationDetails?: MochaInvocationDetails;
order: number;
pending: boolean;
retries: number;
state: string;
sync: boolean;
timedOut: boolean;
timings: Pick<Timing, "lifecycle">;
title: string;
type: string;
wallClockStartedAt: string;
}
}
namespace ScreenshotAfter {
interface Payload {
testAttemptIndex: number;
size: number;
takenAt: string;
dimensions: {
width: number;
height: number;
};
multipart: boolean;
specName: string;
name: string | null;
testFailure: boolean;
path: string;
scaled: boolean;
duration: number;
blackout: string[];
}
}
namespace ModuleAPI {
type Result = CompletedResult | FailureResult;
interface FailureResult {
status: "failed";
failures: number;
message: string;
}
interface CompletedResult {
browserName: string;
browserPath: string;
browserVersion: string;
config: Config;
cypressVersion: string;
endedTestsAt: string;
osName: string;
osVersion: string;
runs: Run[];
startedTestsAt: string;
status: "finished" | "failed";
totalDuration: number;
totalFailed: number;
totalPassed: number;
totalPending: number;
totalSkipped: number;
totalSuites: number;
totalTests: number;
}
interface Run {
error: SpecAfter.Payload["error"];
hooks: SpecAfter.Payload["hooks"];
reporter?: SpecAfter.Payload["reporter"];
reporterStats: SpecAfter.Payload["reporterStats"];
shouldUploadVideo: boolean;
spec: SpecAfter.Spec;
stats: Stats;
tests: Test[] | null;
video: string | null;
}
interface Test {
title: string[];
state: TestState;
body: string;
displayError: string | null;
attempts: TestAttempt[];
}
interface TestAttempt {
state: SpecAfter.TestAttempt["state"];
error: SpecAfter.TestAttempt["error"];
videoTimestamp: number;
duration: number | null;
startedAt: string;
screenshots: Screenshot[];
}
interface Screenshot {
name: string | null;
takenAt: string;
path: string;
height: number;
width: number;
}
interface Stats {
duration: number;
endedAt: string;
failures: number;
passes: number;
pending: number;
skipped: number;
startedAt: string;
suites: number;
tests: number;
}
interface Config {
specPattern: string;
video: boolean;
videoUploadOnPasses: boolean;
version: string;
testingType: TestingType$1;
}
}
}
type TestingType = Cypress.TestingType;
declare enum DebugMode {
None = "none",
All = "all",
Cc = "cc",
Cypress = "cypress",
CommitInfo = "commit-info"
}
type StrippedCypressModuleAPIOptions = Omit<Partial<CypressCommandLine.CypressRunOptions>, "autoCancelAfterFailures" | "tag" | "spec" | "exit" | "headed" | "record" | "headless" | "noExit" | "parallel" | "key" | "tag" | "group" | "ciBuildId" | "cloudConfigFile">;
type CcRunParameters = StrippedCypressModuleAPIOptions & {
ciBuildId?: string;
batchSize?: number;
record?: boolean;
cloudServiceUrl?: string;
env?: object;
group?: string;
recordKey?: string;
parallel?: boolean;
projectId?: string;
spec?: string | string[];
tag?: string | string[];
testingType?: TestingType;
autoCancelAfterFailures?: number | false;
headed?: boolean;
cloudConfigFile?: string;
cloudDebug?: DebugMode | true | string | string[];
experimentalCoverageRecording?: boolean;
};
interface CcRunAPI extends CcRunParameters {
}
declare function run(params?: CcRunAPI): Promise<CypressCommandLine.CypressRunResult | CypressCommandLine.CypressFailedRunResult | {
runUrl: string;
browserName: string;
browserPath: string;
browserVersion: string;
config: Cypress12.ModuleAPI.Config;
cypressVersion: string;
endedTestsAt: string;
osName: string;
osVersion: string;
runs: Cypress12.ModuleAPI.Run[];
startedTestsAt: string;
status: "finished" | "failed";
totalDuration: number;
totalFailed: number;
totalPassed: number;
totalPending: number;
totalSkipped: number;
totalSuites: number;
totalTests: number;
} | undefined>;
export { CcRunAPI, run };

3267
index.js Normal file

File diff suppressed because it is too large Load Diff

3233
index.mjs Normal file

File diff suppressed because it is too large Load Diff

137
package.json Normal file
View File

@@ -0,0 +1,137 @@
{
"name": "@krivega/cc",
"version": "4.0.0",
"main": "./index.js",
"author": {
"name": "Krivega Dmitriy",
"email": "mr.krivega@gmail.com",
"url": "https://krivega.com"
},
"license": "GPL-3.0-or-later",
"engines": {
"node": ">=14.7.0"
},
"scripts": {
"rm": "rimraf out",
"lint": "TIMING=1 eslint \"**/*.ts*\"",
"test": "jest",
"test:watch": "jest --watch",
"release": "release-it",
"release:npm": "npm run build && ./publish.js",
"dev": "tsup-node --watch",
"build": "tsup-node --dts"
},
"devDependencies": {
"@release-it/conventional-changelog": "^7.0.0",
"@swc/core": "^1.3.86",
"@swc/jest": "^0.2.29",
"@types/bluebird": "^3.5.38",
"@types/debug": "^4.1.7",
"@types/getos": "^3.0.1",
"@types/is-ci": "^3.0.0",
"@types/jest": "^29.2.4",
"@types/lodash": "^4.14.191",
"@types/ws": "^8.5.4",
"cypress": "^13.2.0",
"esbuild": "^0.16.5",
"eslint": "^7.32.0",
"eslint-config-custom": "latest",
"jest": "^29.3.1",
"nock": "^13.2.9",
"release-it": "^16.1.5",
"rimraf": "^3.0.2",
"tsconfig": "*",
"tsup": "^7.0.0",
"typescript": "^4.7.4"
},
"dependencies": {
"@cypress/commit-info": "^2.2.0",
"axios": "^1.2.0",
"axios-retry": "^3.4.0",
"bluebird": "^3.7.2",
"chalk": "^4.1.2",
"commander": "^10.0.0",
"common-path-prefix": "^3.0.0",
"cy2": "^3.4.2",
"date-fns": "^2.30.0",
"debug": "^4.3.4",
"execa": "^5.1.1",
"fast-safe-stringify": "^2.1.1",
"getos": "^3.2.1",
"globby": "^11.1.0",
"is-absolute": "^1.0.0",
"lil-http-terminator": "^1.2.3",
"lodash": "^4.17.21",
"nanoid": "^3.3.4",
"plur": "^4.0.0",
"pretty-ms": "^7.0.1",
"source-map-support": "^0.5.21",
"table": "^6.8.1",
"tmp-promise": "^3.0.3",
"ts-pattern": "^4.3.0",
"ws": "^8.13.0"
},
"bin": "./bin/cli.js",
"files": [
"*"
],
"tsup": {
"entry": [
"./index.ts",
"./bin/*.ts",
"./plugin/*.ts",
"./support/*.ts"
],
"external": [
"cypress"
],
"format": [
"cjs",
"esm"
],
"splitting": false,
"shims": true,
"clean": true,
"sourcemap": "inline",
"platform": "node",
"target": "esnext"
},
"exports": {
".": {
"import": "./index.mjs",
"require": "./index.js",
"types": "./index.d.ts"
},
"./plugin": {
"import": "./plugin/index.js",
"require": "./plugin/index.js",
"types": "./plugin/index.d.ts"
},
"./support": {
"import": "./support/index.js",
"require": "./support/index.js",
"types": "./support/index.d.ts"
},
"./package.json": "./package.json"
},
"release-it": {
"github": {
"release": true,
"releaseName": "v${version}"
},
"npm": {
"publish": false
},
"git": {
"requireCleanWorkingDir": false,
"commitMessage": "chore: release v${version}",
"tagName": "v${version}"
},
"plugins": {
"@release-it/conventional-changelog": {
"preset": "angular",
"infile": "../../CHANGELOG.md"
}
}
}
}

3
plugin/index.d.ts vendored Normal file
View File

@@ -0,0 +1,3 @@
declare function cloudPlugin(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions): Promise<Cypress.PluginConfigOptions>;
export { cloudPlugin, cloudPlugin as default };

144
plugin/index.js Normal file
View File

@@ -0,0 +1,144 @@
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var plugin_exports = {};
__export(plugin_exports, {
cloudPlugin: () => cloudPlugin,
default: () => plugin_default
});
module.exports = __toCommonJS(plugin_exports);
var import_debug = __toESM(require("debug"));
var import_fs = __toESM(require("fs"));
var import_util2 = require("util");
var import_ws = __toESM(require("ws"));
var import_chalk = __toESM(require("chalk"));
var import_util = __toESM(require("util"));
var log = (...args) => console.log(import_util.default.format(...args));
var format = import_util.default.format;
var withWarning = (msg) => import_chalk.default.bgYellow.black(" WARNING ") + " " + msg;
var warn = (...args) => log(withWarning(import_util.default.format(...args)));
var cyan = import_chalk.default.cyan;
var blue = import_chalk.default.blueBright;
var red = import_chalk.default.red;
var green = import_chalk.default.greenBright;
var gray = import_chalk.default.gray;
var white = import_chalk.default.white;
var magenta = import_chalk.default.magenta;
var bold = import_chalk.default.bold;
var dim = import_chalk.default.dim;
var Event = ((Event2) => {
Event2["RUN_CANCELLED"] = "run:cancelled";
Event2["RUN_RESULT"] = "run:result";
Event2["TEST_AFTER_RUN"] = "test:after:run";
Event2["TEST_BEFORE_RUN"] = "test:before:run";
Event2["AFTER_SCREENSHOT"] = "after:screenshot";
Event2["AFTER_SPEC"] = "after:spec";
return Event2;
})(Event || {});
var allEvents = Object.values(Event);
var import_events = __toESM(require("events"));
var _debug = (0, import_debug.default)("cc:plugin");
async function cloudPlugin(on, config) {
function debug(...args) {
if (config.env.cc_debug_enabled) {
_debug((0, import_util2.format)(...args));
}
}
if (!config.env.cc_marker) {
warn(
`Cc plugin is not installed properly - missing required variables in ${dim(
"cypress.env"
)}. Please refer to: self`
);
}
let ws = null;
function sendToWS(message) {
if (ws) {
ws.send(JSON.stringify(message));
}
}
if (config.env.cc_ws) {
debug("setting port to %s", config.env.cc_ws);
await new Promise((resolve) => {
ws = new import_ws.default(`ws://localhost:${config.env.cc_ws}`);
ws.on("open", () => {
resolve(null);
});
});
}
on("after:screenshot", (details) => {
sendToWS({
type: "after:screenshot",
payload: details
});
});
on("task", {
"cc:test:after:run": (test) => {
debug("cc:test:after:run task received %o", test);
sendToWS({
type: "test:after:run",
payload: test
});
return null;
},
"cc:test:before:run": (test) => {
debug("cc:test:before:run task received %o", test);
sendToWS({
type: "test:before:run",
payload: test
});
return null;
}
});
on("before:spec", (spec) => {
debug("before:spec task received %o", spec);
sendToWS({ type: "before:spec", payload: { spec } });
});
on("after:spec", (spec, results) => {
debug("after:spec task received %o", spec);
sendToWS({
type: "after:spec",
payload: {
spec,
results
}
});
});
debug("cc plugin loaded");
if (config.env.cc_temp_file) {
debug("dumping config to '%s'", config.env.cc_temp_file);
import_fs.default.writeFileSync(config.env.cc_temp_file, JSON.stringify(config));
debug("config is availabe at '%s'", config.env.cc_temp_file);
}
return config;
}
var plugin_default = cloudPlugin;
0 && (module.exports = {
cloudPlugin
});

113
plugin/index.mjs Normal file
View File

@@ -0,0 +1,113 @@
import Debug from "debug";
import fs from "fs";
import { format as format2 } from "util";
import WebSocket from "ws";
import chalk from "chalk";
import util from "util";
var log = (...args) => console.log(util.format(...args));
var format = util.format;
var withWarning = (msg) => chalk.bgYellow.black(" WARNING ") + " " + msg;
var warn = (...args) => log(withWarning(util.format(...args)));
var cyan = chalk.cyan;
var blue = chalk.blueBright;
var red = chalk.red;
var green = chalk.greenBright;
var gray = chalk.gray;
var white = chalk.white;
var magenta = chalk.magenta;
var bold = chalk.bold;
var dim = chalk.dim;
var Event = ((Event2) => {
Event2["RUN_CANCELLED"] = "run:cancelled";
Event2["RUN_RESULT"] = "run:result";
Event2["TEST_AFTER_RUN"] = "test:after:run";
Event2["TEST_BEFORE_RUN"] = "test:before:run";
Event2["AFTER_SCREENSHOT"] = "after:screenshot";
Event2["AFTER_SPEC"] = "after:spec";
return Event2;
})(Event || {});
var allEvents = Object.values(Event);
var _debug = Debug("cc:plugin");
async function cloudPlugin(on, config) {
function debug(...args) {
if (config.env.cc_debug_enabled) {
_debug(format2(...args));
}
}
if (!config.env.cc_marker) {
warn(
`Cc plugin is not installed properly - missing required variables in ${dim(
"cypress.env"
)}. Please refer to: self`
);
}
let ws = null;
function sendToWS(message) {
if (ws) {
ws.send(JSON.stringify(message));
}
}
if (config.env.cc_ws) {
debug("setting port to %s", config.env.cc_ws);
await new Promise((resolve) => {
ws = new WebSocket(`ws://localhost:${config.env.cc_ws}`);
ws.on("open", () => {
resolve(null);
});
});
}
on("after:screenshot", (details) => {
sendToWS({
type: "after:screenshot",
payload: details
});
});
on("task", {
"cc:test:after:run": (test) => {
debug("cc:test:after:run task received %o", test);
sendToWS({
type: "test:after:run",
payload: test
});
return null;
},
"cc:test:before:run": (test) => {
debug("cc:test:before:run task received %o", test);
sendToWS({
type: "test:before:run",
payload: test
});
return null;
}
});
on("before:spec", (spec) => {
debug("before:spec task received %o", spec);
sendToWS({ type: "before:spec", payload: { spec } });
});
on("after:spec", (spec, results) => {
debug("after:spec task received %o", spec);
sendToWS({
type: "after:spec",
payload: {
spec,
results
}
});
});
debug("cc plugin loaded");
if (config.env.cc_temp_file) {
debug("dumping config to '%s'", config.env.cc_temp_file);
fs.writeFileSync(config.env.cc_temp_file, JSON.stringify(config));
debug("config is availabe at '%s'", config.env.cc_temp_file);
}
return config;
}
var plugin_default = cloudPlugin;
export {
cloudPlugin,
plugin_default as default
};

2
support/index.d.ts vendored Normal file
View File

@@ -0,0 +1,2 @@
export { }

103
support/index.js Normal file

File diff suppressed because one or more lines are too long

79
support/index.mjs Normal file

File diff suppressed because one or more lines are too long