mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-21 22:50:49 -06:00
chore: Intregrate runner packages. (#23028)
* chore: Intregrate runner packages. * Remove unnecessary Studio react files. * Remove unnecessary gif * runner-shared to runner-ct. * fix path. * fix package.json * Remove scss files from runner-ct * Remove runner-ct * Remove runner-shared and runner-ct comments. * Feedback * chore: reduce parallelism for reporter-componen-tests * chore: reduce paralelleism Co-authored-by: Emily Rohrbough <emilyrohrbough@users.noreply.github.com> Co-authored-by: Lachlan Miller <lachlan.miller.1990@outlook.com>
This commit is contained in:
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -40,8 +40,6 @@
|
||||
/packages/rewriter/ @cypress-io/end-to-end
|
||||
/packages/root/ @cypress-io/end-to-end
|
||||
/packages/runner/ @cypress-io/end-to-end
|
||||
/packages/runner-ct/ @cypress-io/component-testing
|
||||
/packages/runner-shared/ @cypress-io/end-to-end
|
||||
/packages/server/ @cypress-io/end-to-end
|
||||
/packages/socket/ @cypress-io/end-to-end
|
||||
/packages/static/ @cypress-io/end-to-end
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -78,9 +78,6 @@ system-tests/lib/fixtureDirs.ts
|
||||
# from npm/webpack-dev-server
|
||||
/npm/webpack-dev-server/cypress/videos
|
||||
|
||||
# from runner-ct
|
||||
/packages/runner-ct/cypress/screenshots
|
||||
|
||||
# from errors
|
||||
/packages/errors/__snapshot-images__
|
||||
/packages/errors/__snapshot-md__
|
||||
|
||||
7
.vscode/terminals.json
vendored
7
.vscode/terminals.json
vendored
@@ -83,13 +83,6 @@
|
||||
"cwd": "[cwd]/packages/runner",
|
||||
"command": "yarn watch"
|
||||
},
|
||||
{
|
||||
"name": "packages/runner-ct watch",
|
||||
"focus": true,
|
||||
"onlySingle": true,
|
||||
"cwd": "[cwd]/packages/runner-ct",
|
||||
"command": "yarn watch"
|
||||
},
|
||||
{
|
||||
"name": "packages/driver cypress open",
|
||||
"focus": true,
|
||||
|
||||
@@ -271,8 +271,6 @@ Here is a list of the core packages in this repository with a short description,
|
||||
| [reporter](./packages/reporter) | `@packages/reporter` | The reporter shows the running results of the tests (The Command Log UI). |
|
||||
| [root](./packages/root) | `@packages/root` | Dummy package pointing at the root of the repository. |
|
||||
| [runner](./packages/runner) | `@packages/runner` | The runner is the minimal "chrome" around the user's application under test. |
|
||||
| [runner-ct](./packages/runner-ct) | `@packages/runner-ct` | The runner for component testing |
|
||||
| [runner-shared](./packages/runner-shared) | `@packages/runner-shared` | The shared components between the `runner` and the `runner-ct` packages |
|
||||
| [server](./packages/server) | `@packages/server` | The <3 of Cypress. This orchestrates everything. The backend node process. |
|
||||
| [server-ct](./packages/server-ct) | `@packages/server-ct` | Some Component Testing specific overrides. Mostly extends functionality from `@packages/server` |
|
||||
| [socket](./packages/socket) | `@packages/socket` | A wrapper around socket.io to provide common libraries. |
|
||||
|
||||
@@ -1607,7 +1607,7 @@ jobs:
|
||||
percy:
|
||||
type: boolean
|
||||
default: false
|
||||
parallelism: 7
|
||||
parallelism: 2
|
||||
steps:
|
||||
- run-new-ui-tests:
|
||||
browser: chrome
|
||||
|
||||
@@ -91,13 +91,13 @@ The terminology can get a bit confusing as Vue Router's `params` are not the que
|
||||
|
||||
## Using existing, Vite-incompatible modules
|
||||
|
||||
Some of our modules, like `@packages/reporter`, `@packages/driver` and `@packages/runner-shared` cannot be easily
|
||||
Some of our modules, like `@packages/reporter`, `@packages/driver` and `@packages/runner` cannot be easily
|
||||
used with Vite due to circular dependencies and modules that do not have compatible ESM builds.
|
||||
|
||||
To work around this, when consuming existing code, it is bundled with webpack and made available under the
|
||||
`window.UnifiedRunner` namespace. It is injected via [`injectBundle`](./src/runner/injectBundle.ts).
|
||||
|
||||
To add more code to the bundle, add it in the bundle root, `@packages/runner-ct/src/main.tsx` and attach it to
|
||||
To add more code to the bundle, add it in the bundle root, `@packages/runner/src/main.tsx` and attach it to
|
||||
`window.UnifiedRunner`.
|
||||
|
||||
As a rule of thumb, avoid importing from the older, webpack based modules into this package. Instead, if you want to consume code from those older, webpack bundled modules, you should add them to the webpack root and consume them via `window.UnifiedRunner`. Ideally, update [`index.d.ts`](./index.d.ts) to add the types, as well.
|
||||
|
||||
4
packages/app/index.d.ts
vendored
4
packages/app/index.d.ts
vendored
@@ -51,11 +51,11 @@ declare global {
|
||||
|
||||
/**
|
||||
* Any React components or general code needed from
|
||||
* runner-shared, reporter or driver are also bundled with
|
||||
* runner, reporter or driver are also bundled with
|
||||
* webpack and made available via the window.UnifedRunner namespace.
|
||||
*
|
||||
* We cannot import the correct types, because this causes the linter and type
|
||||
* checker to run on runner-shared and reporter, and it blows up.
|
||||
* checker to run on runner and reporter, and it blows up.
|
||||
*/
|
||||
Reporter: any
|
||||
shortcuts: {
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
* - reporter
|
||||
* which are built with React and bundle with webpack.
|
||||
*
|
||||
* The entry point for the webpack bundle is `runner-ct/main.tsx`.
|
||||
* The entry point for the webpack bundle is `runner/main.tsx`.
|
||||
* Any time you need to consume some existing code, add it to the `window.UnifiedRunner`
|
||||
* namespace there, and access it with `window.UnifiedRunner`.
|
||||
*
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
"@packages/network": "0.0.0-development",
|
||||
"@packages/rewriter": "0.0.0-development",
|
||||
"@packages/runner": "0.0.0-development",
|
||||
"@packages/runner-shared": "0.0.0-development",
|
||||
"@packages/server": "0.0.0-development",
|
||||
"@packages/socket": "0.0.0-development",
|
||||
"@packages/ts": "0.0.0-development",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import $ from 'jquery'
|
||||
import $dimensions from '@packages/runner-shared/src/dimensions'
|
||||
import $dimensions from '@packages/runner/src/dom/dimensions'
|
||||
|
||||
const resetStyles = `
|
||||
border: none !important;
|
||||
|
||||
@@ -2,7 +2,7 @@ import path from 'path'
|
||||
|
||||
let fs: typeof import('fs-extra')
|
||||
|
||||
export type RunnerPkg = 'app' | 'runner' | 'runner-ct'
|
||||
export type RunnerPkg = 'app' | 'runner'
|
||||
|
||||
type FoldersWithDist = 'static' | 'driver' | RunnerPkg | 'launchpad'
|
||||
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"cypress",
|
||||
"@cypress/dev"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:@cypress/dev/general",
|
||||
"plugin:@cypress/dev/tests",
|
||||
"plugin:@cypress/dev/react",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"../reporter/src/.eslintrc.json"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"react/display-name": "off",
|
||||
"react/function-component-definition": [
|
||||
"error",
|
||||
{
|
||||
"namedComponents": "arrow-function",
|
||||
"unnamedComponents": "arrow-function"
|
||||
}
|
||||
],
|
||||
"react/jsx-boolean-value": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"react/jsx-closing-bracket-location": [
|
||||
"error",
|
||||
"line-aligned"
|
||||
],
|
||||
"react/jsx-closing-tag-location": "error",
|
||||
"react/jsx-curly-brace-presence": [
|
||||
"error",
|
||||
{
|
||||
"props": "never",
|
||||
"children": "never"
|
||||
}
|
||||
],
|
||||
"react/jsx-curly-newline": "error",
|
||||
"react/jsx-filename-extension": [
|
||||
"warn",
|
||||
{
|
||||
"extensions": [
|
||||
".js",
|
||||
".jsx",
|
||||
".tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"react/jsx-first-prop-new-line": "error",
|
||||
"react/jsx-max-props-per-line": [
|
||||
"error",
|
||||
{
|
||||
"maximum": 1,
|
||||
"when": "multiline"
|
||||
}
|
||||
],
|
||||
"react/jsx-no-bind": [
|
||||
"error",
|
||||
{
|
||||
"ignoreDOMComponents": true
|
||||
}
|
||||
],
|
||||
"react/jsx-no-useless-fragment": "error",
|
||||
"react/jsx-one-expression-per-line": [
|
||||
"error",
|
||||
{
|
||||
"allow": "literal"
|
||||
}
|
||||
],
|
||||
"react/jsx-sort-props": [
|
||||
"error",
|
||||
{
|
||||
"callbacksLast": true,
|
||||
"ignoreCase": true,
|
||||
"noSortAlphabetically": true,
|
||||
"reservedFirst": true
|
||||
}
|
||||
],
|
||||
"react/jsx-tag-spacing": [
|
||||
"error",
|
||||
{
|
||||
"closingSlash": "never",
|
||||
"beforeSelfClosing": "always"
|
||||
}
|
||||
],
|
||||
"react/jsx-wrap-multilines": [
|
||||
"error",
|
||||
{
|
||||
"declaration": "parens-new-line",
|
||||
"assignment": "parens-new-line",
|
||||
"return": "parens-new-line",
|
||||
"arrow": "parens-new-line",
|
||||
"condition": "parens-new-line",
|
||||
"logical": "parens-new-line",
|
||||
"prop": "parens-new-line"
|
||||
}
|
||||
],
|
||||
"react/no-array-index-key": "error",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/prop-types": "off",
|
||||
"quote-props": [
|
||||
"error",
|
||||
"as-needed"
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"lib/*"
|
||||
],
|
||||
"rules": {
|
||||
"no-console": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"**/*.json"
|
||||
],
|
||||
"rules": {
|
||||
"quotes": "off",
|
||||
"comma-dangle": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.tsx",
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"react/jsx-no-bind": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
1
packages/runner-ct/.gitignore
vendored
1
packages/runner-ct/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
cypress/videos/*
|
||||
@@ -1,6 +0,0 @@
|
||||
# Runner CT
|
||||
|
||||
This is an old package, deprecated in favor of `@packages/app`. It has two remaining responsibilities before it can be entirely removed:
|
||||
|
||||
1. Bundles `@packages/reporter` and `@packages/driver` via webpack. Once those can be directly imported to `@packages/app`, we can remove this.
|
||||
2. Bundles styles for `@packages/reporter`, loaded in `main.scss`. Ideally, reporter should import its own styles.
|
||||
@@ -1,69 +0,0 @@
|
||||
{
|
||||
"name": "@packages/runner-ct",
|
||||
"version": "0.0.0-development",
|
||||
"private": true,
|
||||
"browser": "src/index.js",
|
||||
"scripts": {
|
||||
"build": "node ../../scripts/run-webpack",
|
||||
"build-prod": "cross-env NODE_ENV=production yarn build && tsc",
|
||||
"clean-deps": "rimraf node_modules",
|
||||
"cypress:open": "ts-node ../../scripts/cypress.js open --component --project .",
|
||||
"cypress:run": "ts-node ../../scripts/cypress.js run --component --project .",
|
||||
"postinstall": "echo '@packages/runner needs: yarn build'",
|
||||
"lint": "eslint --ext .js,.jsx,.ts,.tsx,.json src",
|
||||
"test": "ts-node ../../scripts/cypress.js run --component --project .",
|
||||
"watch": "node ../../scripts/run-webpack --watch --progress --config webpack.config.ts"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.12.3",
|
||||
"@babel/preset-env": "^7.12.1",
|
||||
"@cypress/react-tooltip": "0.5.3",
|
||||
"@fortawesome/free-regular-svg-icons": "5.15.2",
|
||||
"@fortawesome/react-fontawesome": "^0.1.17",
|
||||
"@packages/driver": "0.0.0-development",
|
||||
"@packages/icons": "0.0.0-development",
|
||||
"@types/http-proxy": "1.17.4",
|
||||
"@types/node": "14.14.31",
|
||||
"@types/sockjs-client": "1.1.0",
|
||||
"babel-loader": "8.1.0",
|
||||
"bluebird": "3.5.3",
|
||||
"cash-dom": "^8.1.0",
|
||||
"chai": "^4.2.0",
|
||||
"classnames": "2.3.1",
|
||||
"clean-webpack-plugin": "^3.0.0",
|
||||
"cypress-real-events": "1.6.0",
|
||||
"eslint-plugin-mocha": "^8.0.0",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"express": "^4.17.1",
|
||||
"fuzzysort": "^1.1.4",
|
||||
"hotkeys-js": "3.8.2",
|
||||
"html-webpack-plugin": "^4.5.0",
|
||||
"koa": "^2.13.0",
|
||||
"mobx": "5.15.4",
|
||||
"mobx-react": "6.1.8",
|
||||
"mocha": "^8.1.3",
|
||||
"nanoid": "3.1.31",
|
||||
"react": "16.8.6",
|
||||
"react-devtools-inline": "^4.10.1",
|
||||
"react-dom": "16.8.6",
|
||||
"react-split-pane": "^0.1.92",
|
||||
"rimraf": "3.0.2",
|
||||
"sass": "1.44.0",
|
||||
"sass-loader": "^10.0.3",
|
||||
"sockjs-client": "^1.5.0",
|
||||
"strip-ansi": "6.0.0",
|
||||
"ts-loader": "^8.0.5",
|
||||
"ts-node": "^10.2.1",
|
||||
"watch": "^1.0.2",
|
||||
"webpack": "^4.44.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"webpack": "^4.0.0 || ^5.0.0",
|
||||
"webpack-dev-middleware": "*"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
@use '../../variables.scss' as *;
|
||||
|
||||
.specs-list-search-input-container {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
background-color: white;
|
||||
box-shadow: $shadow-xs;
|
||||
z-index: 1;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
font-size: 18px;
|
||||
height: 32px;
|
||||
color: #848484;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #E8E8EC;
|
||||
padding: 0 8px 0 16px;
|
||||
|
||||
|
||||
&::placeholder {
|
||||
color: #B4B5BC;
|
||||
}
|
||||
|
||||
// avoid default focus outline because of input border radius
|
||||
&:focus {
|
||||
outline: none;
|
||||
box-shadow: 0px 0px 2px #0012ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
.keyboard-helper-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
background-color: white;
|
||||
|
||||
.keyboard-helper {
|
||||
padding: 8px 32px;
|
||||
color: #555;
|
||||
// background: white;
|
||||
font-family: "Mulish", "Helvetica Neue", "Arial", sans-serif;
|
||||
font-size: 13px;
|
||||
width: 224px;
|
||||
|
||||
.keyboard-shortcut {
|
||||
display: flex;
|
||||
margin-top: 8px;
|
||||
height: 23px;
|
||||
justify-content: space-between;
|
||||
|
||||
.shortcut {
|
||||
display: flex;
|
||||
|
||||
.key {
|
||||
display: flex;
|
||||
font-family: sans-serif; // display keys symbols correctly
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid rgba(255, 255, 255, 0.4);
|
||||
height: 23px;
|
||||
min-width: 23px;
|
||||
margin-right: 4px;
|
||||
padding: 0px 4px;
|
||||
font-size: 0.8125rem;
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
background-color: #ddd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,36 +0,0 @@
|
||||
.no-spec {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
color: #555;
|
||||
background: white;
|
||||
font-family: "Mulish", "Helvetica Neue", "Arial", sans-serif;
|
||||
font-size: 13px;
|
||||
|
||||
.no-spec-content-container {
|
||||
display: flex;
|
||||
flex-basis: 45%;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
a {
|
||||
color: #3386D4;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.no-spec-title {
|
||||
margin-top: 16px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.no-spec-custom-children {
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
packages/runner-ct/src/app/NoSpec.scss.d.ts
vendored
7
packages/runner-ct/src/app/NoSpec.scss.d.ts
vendored
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,5 +0,0 @@
|
||||
@use '../variables' as *;
|
||||
|
||||
.ctReporterHeader {
|
||||
min-height: $runner-ct-header-height;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'ctReporterHeader': string;
|
||||
'display-none': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,134 +0,0 @@
|
||||
@use '../variables' as *;
|
||||
|
||||
$box-shadow-closest: 0px 0px 5px rgba(0, 0, 0, 0.4);
|
||||
|
||||
.app {
|
||||
display: flex;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.appWrapper {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.appWrapperScreenshotting {
|
||||
margin-inline: 0;
|
||||
}
|
||||
|
||||
.runnerCt {
|
||||
left: 0;
|
||||
|
||||
header {
|
||||
position: static;
|
||||
top: unset;
|
||||
left: unset;
|
||||
right: unset;
|
||||
bottom: unset;
|
||||
min-height: $runner-ct-header-height;
|
||||
}
|
||||
|
||||
.size-container {
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
}
|
||||
|
||||
.noSpecAut {
|
||||
background: white;
|
||||
}
|
||||
|
||||
.screenshotting {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.leftNav {
|
||||
background: $left-nav-background-color;
|
||||
z-index: 4;
|
||||
border-right: 1px solid $border-color;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.runner {
|
||||
box-shadow: shadow(s);
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
.reporter {
|
||||
box-shadow: shadow(l);
|
||||
background: $reporter-background-color;
|
||||
// border-right: 1px solid $border-color;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.ctPlugins {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
||||
.ctPluginsHeader {
|
||||
height: 40px; // make sure this is hardcoded in as well RunnerCt.tsx
|
||||
display: flex;
|
||||
border-top: 1px solid $metal-20;
|
||||
|
||||
.ctTogglePluginsSectionButton {
|
||||
margin-left: auto;
|
||||
margin-right: 4px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
transition: transform .3s ease-in-out;
|
||||
|
||||
&.ctTogglePluginsSectionButtonOpen {
|
||||
will-change: transform;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.ctPluginToggleButton {
|
||||
font-family: $font-stack-sans;
|
||||
cursor: pointer;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 0 16px;
|
||||
transition: border-bottom-color .3s ease-in-out;
|
||||
|
||||
:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.ctPluginsName {
|
||||
padding: 2px 4px;
|
||||
border-bottom: 2px solid transparent;
|
||||
|
||||
&:hover {
|
||||
border-bottom: 2px solid $chill-40;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ctDevtoolsContainer {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.largerIcon {
|
||||
font-size: 1.75rem !important;
|
||||
}
|
||||
|
||||
.noSpecsDescription {
|
||||
text-align: center;
|
||||
margin: 0 1rem;
|
||||
line-height: 1.5;
|
||||
|
||||
.folder {
|
||||
border-radius: 4px;
|
||||
padding: 1px 4px;
|
||||
background-color: #ddd;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'app': string;
|
||||
'appWrapper': string;
|
||||
'appWrapperScreenshotting': string;
|
||||
'ctDevtoolsContainer': string;
|
||||
'ctPluginToggleButton': string;
|
||||
'ctPlugins': string;
|
||||
'ctPluginsHeader': string;
|
||||
'ctPluginsName': string;
|
||||
'ctTogglePluginsSectionButton': string;
|
||||
'ctTogglePluginsSectionButtonOpen': string;
|
||||
'display-none': string;
|
||||
'folder': string;
|
||||
'largerIcon': string;
|
||||
'leftNav': string;
|
||||
'noSpecAut': string;
|
||||
'noSpecsDescription': string;
|
||||
'reporter': string;
|
||||
'runner': string;
|
||||
'runnerCt': string;
|
||||
'screenshotting': string;
|
||||
'size-container': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,102 +0,0 @@
|
||||
@use "../variables.scss" as *;
|
||||
@import "../runner-ct-variables.scss";
|
||||
@import "../../../reporter/src/lib/variables.scss";
|
||||
|
||||
/**
|
||||
* Styles that cannot be transformed by scoped modules should live here. Examples are:
|
||||
* - override Runner globals (in a pinch)
|
||||
* - publicly interface with 3rd party libs (Resizer)
|
||||
*/
|
||||
|
||||
body, html {
|
||||
font-size: 1rem !important;
|
||||
font-family: $font-stack-sans;
|
||||
font-size: text(m);
|
||||
|
||||
* :focus {
|
||||
outline-offset: 1px;
|
||||
outline-width: 1px;
|
||||
outline-color: $chill-20;
|
||||
outline-style: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.reporter {
|
||||
.runnable-header {
|
||||
box-shadow: shadow(m);
|
||||
}
|
||||
}
|
||||
|
||||
.runner {
|
||||
// @include checkerboard();
|
||||
background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1IiBoZWlnaHQ9IjUiPgo8cmVjdCB3aWR0aD0iNSIgaGVpZ2h0PSI1IiBmaWxsPSIjZGJkYmRiIj48L3JlY3Q+CjxwYXRoIGQ9Ik0wIDVMNSAwWk02IDRMNCA2Wk0tMSAxTDEgLTFaIiBzdHJva2U9IiNjNGM0YzQiIHN0cm9rZS13aWR0aD0iMSI+PC9wYXRoPgo8L3N2Zz4=");
|
||||
}
|
||||
|
||||
.aut-iframe-screenshotting {
|
||||
height: min(100vh, 100%) !important;
|
||||
overflow: scroll !important;
|
||||
}
|
||||
|
||||
// Prevent left-most Resizer from showing up when the pane is hidden.
|
||||
.isSpecsListClosed {
|
||||
> .Resizer {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
// Must be globally scoped. Bummer.
|
||||
$resizerLineSize: 4px;
|
||||
|
||||
.Resizer {
|
||||
$resize-thickness: 12px;
|
||||
background: none;
|
||||
transition: background-color 200ms ease-in-out;
|
||||
z-index: 10;
|
||||
box-sizing: border-box;
|
||||
background-clip: padding-box;
|
||||
&:after {
|
||||
content: '';
|
||||
position: relative;
|
||||
display: block;
|
||||
background: transparent;
|
||||
transition: background 200ms ease;
|
||||
position: fixed;
|
||||
}
|
||||
&:hover {
|
||||
&:after {
|
||||
background: $chill-30;
|
||||
}
|
||||
}
|
||||
|
||||
&.horizontal {
|
||||
margin: -($resize-thickness * 0.5) 0;
|
||||
height: $resize-thickness;
|
||||
width: 100%;
|
||||
cursor: row-resize;
|
||||
border-top: 5px solid rgba(255, 255, 255, 0);
|
||||
border-bottom: 5px solid rgba(255, 255, 255, 0);
|
||||
|
||||
&:after {
|
||||
height: $resizerLineSize;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
margin: 0 -($resize-thickness * 0.5);
|
||||
width: $resize-thickness;
|
||||
height: 100%;
|
||||
cursor: col-resize;
|
||||
border-left: 5px solid rgba(255, 255, 255, 0);
|
||||
border-right: 5px solid rgba(255, 255, 255, 0);
|
||||
|
||||
&:after {
|
||||
width: $resizerLineSize;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,20 +0,0 @@
|
||||
@use '../variables.scss' as *;
|
||||
|
||||
.iframes-ct-container {
|
||||
margin: 0 8px;
|
||||
padding: 16px 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.iframes-ct-container-screenshotting {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.size-container {
|
||||
overflow: auto;
|
||||
box-shadow: shadow(m);
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,3 +0,0 @@
|
||||
import '@packages/runner/src/main.scss'
|
||||
|
||||
import './main'
|
||||
@@ -1,3 +0,0 @@
|
||||
.logo {
|
||||
max-width: 100%;
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
@use 'baseColors' as *;
|
||||
@use 'semanticColors' as *;
|
||||
@use 'typography' as *;
|
||||
|
||||
$left-nav-width: 48px;
|
||||
$icon-color: $metal-20;
|
||||
$active-color: $brand-01;
|
||||
|
||||
.leftNav {
|
||||
display: grid;
|
||||
grid-template-columns: $left-nav-width;
|
||||
grid-template-rows: auto auto;
|
||||
width: $left-nav-width;
|
||||
margin: 0;
|
||||
row-gap: 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.top, .bottom {
|
||||
display: grid;
|
||||
list-style-type: none;
|
||||
row-gap: 0.5rem;
|
||||
grid-template-rows: repeat(auto-fit, 48px)
|
||||
}
|
||||
|
||||
.top {
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
display: grid;
|
||||
align-content: flex-end;
|
||||
padding-bottom: 2rem;
|
||||
}
|
||||
|
||||
.item {
|
||||
height: 100%;
|
||||
font-size: text(ml);
|
||||
cursor: pointer;
|
||||
color: $icon-color;
|
||||
|
||||
&:before {
|
||||
content: '';
|
||||
width: 4px;
|
||||
position: absolute;
|
||||
height: $left-nav-width;
|
||||
display: block;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.active {
|
||||
color: $active-color;
|
||||
|
||||
&:before {
|
||||
background: $brand-01;
|
||||
}
|
||||
}
|
||||
|
||||
.inactive {
|
||||
:hover {
|
||||
|
||||
color: $active-color;
|
||||
}
|
||||
}
|
||||
|
||||
.itemAnchor {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
margin: auto;
|
||||
height: 100%;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
@use 'spacing' as *;
|
||||
@use 'semanticColors' as *;
|
||||
@use 'css-util' as *;
|
||||
|
||||
.group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.header {
|
||||
width: 100%;
|
||||
|
||||
cursor: pointer;
|
||||
@include no-selection;
|
||||
|
||||
&:hover {
|
||||
background-color: $button-white-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $button-white-push-color;
|
||||
}
|
||||
}
|
||||
|
||||
.disabled {
|
||||
color: grey;
|
||||
|
||||
.title {
|
||||
cursor: unset;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.content {
|
||||
// TODO: Add transition
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.expanded {
|
||||
.content {
|
||||
flex-grow: 1;
|
||||
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
@use 'semanticColors' as *;
|
||||
@use 'spacing' as *;
|
||||
@use 'typography' as *;
|
||||
@use 'css-util' as *;
|
||||
|
||||
.tree {
|
||||
> div {
|
||||
// Container div for nodes
|
||||
padding-bottom: spacing(l);
|
||||
}
|
||||
}
|
||||
|
||||
.node {
|
||||
display: grid;
|
||||
grid-template-columns: spacing(m) 1fr;
|
||||
|
||||
column-gap: spacing(xs);
|
||||
align-items: center;
|
||||
|
||||
background: repeating-linear-gradient(90deg, $control-slight-color, $control-slight-color 1px, transparent 1px, transparent spacing(m), );
|
||||
background-repeat: no-repeat;
|
||||
background-size: 0 100%;
|
||||
// Start background at 1/2 indent spacing (m = 1rem)
|
||||
background-position-x: spacing(s);
|
||||
|
||||
@include text(ms);
|
||||
|
||||
:global(.svg-inline--fa) {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
> :first-child {
|
||||
justify-self: center;
|
||||
}
|
||||
}
|
||||
|
||||
.file {
|
||||
cursor: pointer;
|
||||
@include no-selection;
|
||||
|
||||
&:hover {
|
||||
background-color: $button-white-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $button-white-push-color;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
color: $control-text-color-white;
|
||||
background: none;
|
||||
background-color: $button-blue-color;
|
||||
|
||||
&:hover {
|
||||
background-color: $button-blue-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $button-blue-hover-color;
|
||||
}
|
||||
}
|
||||
|
||||
.highlight {
|
||||
> span {
|
||||
font-weight: $highlight-weight;
|
||||
}
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
text-align: center;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
@use 'surfaces' as *;
|
||||
|
||||
.focusWrapper {
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.child {
|
||||
display: grid;
|
||||
grid-template-rows: 1fr;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.focus {
|
||||
@include focused;
|
||||
|
||||
&::after {
|
||||
// TODO: Improve this
|
||||
border-radius: 0;
|
||||
// border-width: 1px;
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
@use 'semanticColors' as *;
|
||||
@use 'typography' as *;
|
||||
@use 'spacing' as *;
|
||||
@use 'surfaces' as *;
|
||||
@use 'func' as *;
|
||||
@use 'css-util' as util;
|
||||
|
||||
$button-vertical-padding: change-rem-unit-to-em(spacing(xs));
|
||||
$button-horizontal-padding: change-rem-unit-to-em(spacing(s));
|
||||
|
||||
.button {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
// Reset
|
||||
@include util.no-selection;
|
||||
border: 0;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
|
||||
// Style
|
||||
padding: $button-vertical-padding $button-horizontal-padding;
|
||||
border-radius: $button-radius;
|
||||
|
||||
color: $control-text-color-white;
|
||||
background-color: $button-blue-color;
|
||||
|
||||
&:hover {
|
||||
background-color: $button-blue-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $button-blue-push-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&.white {
|
||||
color: $control-text-color-black;
|
||||
background-color: $button-white-color;
|
||||
|
||||
border: 1px solid $control-border-color;
|
||||
|
||||
&:hover {
|
||||
background-color: $button-white-hover-color;
|
||||
}
|
||||
|
||||
&:active {
|
||||
background-color: $button-white-push-color;
|
||||
}
|
||||
}
|
||||
|
||||
&.disableBorder {
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
:local(.button.white:not(.disableBorder)) {
|
||||
&.focused::after {
|
||||
// White buttons have a border that needs to be compensated for
|
||||
top: -1px;
|
||||
left: -1px;
|
||||
right: -1px;
|
||||
bottom: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
$icon-margin: 0.15em;
|
||||
$icon-bottom-offset: 0.125em;
|
||||
|
||||
$icon-size: 1em - $icon-margin * 2;
|
||||
|
||||
:global(.svg-inline--fa) {
|
||||
// TODO: Is there ever a need for the icon to not take a square space as long as it's properly centered?
|
||||
&.icon {
|
||||
position: relative;
|
||||
|
||||
width: $icon-size;
|
||||
height: $icon-size;
|
||||
|
||||
bottom: $icon-bottom-offset;
|
||||
}
|
||||
|
||||
&.ignoreTextCenter {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
|
||||
bottom: auto;
|
||||
}
|
||||
|
||||
&.sizeWithoutCenter {
|
||||
bottom: auto;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
.icon {
|
||||
background-color: orange;
|
||||
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.textIcon {
|
||||
border: 1px solid black;
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
@use 'spacing' as *;
|
||||
@use 'semanticColors' as *;
|
||||
@use '../icon/Icon.module.scss' as *;
|
||||
@use 'surfaces' as *;
|
||||
|
||||
$icon-overall-size: 1.5em;
|
||||
$input-icon-margin: 0.25em;
|
||||
|
||||
.iconInput {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
// No actual border drawn. This provides the mask for the rounded corners to clip child elements
|
||||
border-radius: $button-radius;
|
||||
overflow: hidden;
|
||||
|
||||
z-index: 0;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
border: 1px solid $control-border-color;
|
||||
border-radius: $button-radius;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
display: flex;
|
||||
flex-grow: 1;
|
||||
|
||||
&:first-child {
|
||||
// If first child, apply border padding
|
||||
padding-left: spacing(s);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
// If last child, apply border padding
|
||||
padding-right: spacing(s);
|
||||
}
|
||||
}
|
||||
|
||||
.input {
|
||||
flex-grow: 1;
|
||||
// Required to allow input to shrink in certain size scenarios
|
||||
width: 0;
|
||||
padding: 0;
|
||||
|
||||
background-color: transparent;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
flex-grow: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
// Icon
|
||||
margin: 0 $input-icon-margin;
|
||||
bottom: 0;
|
||||
|
||||
color: $control-text-color-black;
|
||||
}
|
||||
|
||||
.iconButton {
|
||||
// See global expression below
|
||||
// Make sure button fills entire height, to enable the button focus ring to cover the IconInput border
|
||||
align-self: stretch;
|
||||
|
||||
padding: 0 $input-icon-margin;
|
||||
line-height: 1;
|
||||
|
||||
border-radius: 0;
|
||||
|
||||
&::after {
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:global {
|
||||
:local(.iconButton) {
|
||||
&.focused {
|
||||
// Set overflow and border radius to clip corners when focused
|
||||
overflow: hidden;
|
||||
|
||||
border-radius: $button-radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
@use 'semanticColors' as *;
|
||||
@use 'surfaces' as *;
|
||||
@use 'spacing' as *;
|
||||
|
||||
input.input {
|
||||
padding: 0 spacing(s);
|
||||
|
||||
font-weight: normal;
|
||||
|
||||
border: 1px solid $control-border-color;
|
||||
border-radius: $button-radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for standalone inputs to allow for a proper focus ring
|
||||
*/
|
||||
.wrapper {
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@use 'semanticColors' as *;
|
||||
|
||||
.placeholder {
|
||||
color: $control-text-color-dim;
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
@import './func.scss';
|
||||
|
||||
$colors: (
|
||||
metal-100: rgba(0, 0, 0, 1), // #000000;
|
||||
metal-90: rgba(33, 36, 38, 1), // #212426;
|
||||
metal-80: rgba(45, 49, 52, 1), // #2d3134;
|
||||
metal-70: rgba(62, 67, 71, 1), // #3e4347;
|
||||
metal-60: rgba(83, 90, 95, 1), // #535a5f;
|
||||
metal-50: rgba(107, 116, 123, 1), // #6b747b;
|
||||
metal-40: rgba(135, 144, 151, 1), // #879097;
|
||||
metal-30: rgba(160, 167, 172, 1), // #a0a7ac;
|
||||
metal-20: rgba(190, 194, 198, 1), // #bec2c6;
|
||||
metal-10: rgba(230, 232, 234, 1), // #e6e8ea;
|
||||
metal-05: rgba(244, 245, 246, 1), // #f4f5f6;
|
||||
metal-00: rgba(255, 255, 255, 1), // #ffffff;
|
||||
red-70: rgba(153, 11, 18, 1), // #990b12;
|
||||
red-60: rgba(191, 13, 22, 1), // #bf0d16;
|
||||
red-50: rgba(224, 16, 26, 1), // #e0101a;
|
||||
red-40: rgba(241, 55, 64, 1), // #f13740;
|
||||
chill-90: rgba(8, 33, 68, 1), // #082144;
|
||||
chill-80: rgba(12, 49, 100, 1), // #0c3164;
|
||||
chill-70: rgba(16, 66, 137, 1), // #104289;
|
||||
chill-60: rgba(21, 86, 178, 1), // #1556b2;
|
||||
chill-50: rgba(27, 111, 228, 1), // #1b6fe4;
|
||||
chill-40: rgba(73, 142, 238, 1), // #498eee;
|
||||
chill-30: rgba(118, 168, 239, 1), // #76a8ef;
|
||||
chill-20: rgba(164, 197, 244, 1), // #a4c5f4;
|
||||
chill-10: rgba(222, 235, 252, 1), // #deebfc;
|
||||
chill-05: rgba(237, 243, 253, 1), // #edf3fd;
|
||||
olive-60: rgba(93, 100, 12, 1), // #5d640c;
|
||||
olive-50: rgba(114, 123, 15, 1), // #727b0f;
|
||||
olive-40: rgba(143, 154, 25, 1), // #8f9a19;
|
||||
olive-30: rgba(211, 228, 27, 1), // #d3e41b;
|
||||
olive-20: rgba(225, 237, 100, 1), // #e1ed64;
|
||||
olive-10: rgba(238, 245, 168, 1), // #eef5a8;
|
||||
olive-05: rgba(246, 250, 209, 1), // #f6fad1;
|
||||
papaya-60: rgba(143, 68, 10, 1), // #8f440a;
|
||||
papaya-50: rgba(190, 90, 14, 1), // #be5a0e;
|
||||
papaya-40: rgba(235, 107, 10, 1), // #eb6b0a;
|
||||
papaya-30: rgba(242, 141, 64, 1), // #f28d40;
|
||||
papaya-20: rgba(246, 175, 121, 1), // #f6af79;
|
||||
papaya-10: rgba(252, 229, 212, 1), // #fce5d4;
|
||||
papaya-05: rgba(253, 241, 231, 1), // #fdf1e7;
|
||||
green-60: rgba(41, 102, 10, 1), // #29660a;
|
||||
green-50: rgba(54, 133, 15, 1), // #36850f;
|
||||
green-40: rgba(68, 164, 20, 1), // #44a414;
|
||||
green-30: rgba(79, 191, 23, 1), // #4fbf17;
|
||||
green-20: rgba(107, 219, 51, 1), // #6bdb33;
|
||||
green-10: rgba(204, 244, 185, 1), // #ccf4b9;
|
||||
green-05: rgba(236, 251, 228, 1), // #ecfbe4;
|
||||
cran-50: rgba(228, 28, 95, 1), // #e41c5f;
|
||||
brand-00: rgba(28, 228, 150, 1), // #1ce496;
|
||||
// TODO: Rewrite these names
|
||||
brand-01: rgba(8, 41, 63, 1), // #08293f;
|
||||
accent-00: rgba(177, 99, 255, 1), // #b163ff;
|
||||
accent-01: rgba(54, 197, 255, 1), // #36c5ff;
|
||||
accent-02: rgba(230, 255, 30, 1), // #e6ff1e;
|
||||
);
|
||||
|
||||
// TODO: Is this needed?
|
||||
// :root {
|
||||
// @each $name, $color in $colors {
|
||||
// .text-#{"" + $name} {
|
||||
// color: $color;
|
||||
// }
|
||||
// .bg-#{"" + $name} {
|
||||
// background-color: $color;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// --- Color Variables
|
||||
|
||||
@function color($name: string) {
|
||||
@return var(--#{"" + $name});
|
||||
}
|
||||
|
||||
// Must be manually written out as SASS does not support dynamic variable creation
|
||||
// Exposes SASS variables as references to CSS variables
|
||||
$metal-100: color('metal-100');
|
||||
$metal-90: color('metal-90');
|
||||
$metal-80: color('metal-80');
|
||||
$metal-70: color('metal-70');
|
||||
$metal-60: color('metal-60');
|
||||
$metal-50: color('metal-50');
|
||||
$metal-40: color('metal-40');
|
||||
$metal-30: color('metal-30');
|
||||
$metal-20: color('metal-20');
|
||||
$metal-10: color('metal-10');
|
||||
$metal-05: color('metal-05');
|
||||
$metal-00: color('metal-00');
|
||||
|
||||
$red-70: color('red-70');
|
||||
$red-60: color('red-60');
|
||||
$red-50: color('red-50');
|
||||
$red-40: color('red-40');
|
||||
|
||||
$chill-90: color('chill-90');
|
||||
$chill-80: color('chill-80');
|
||||
$chill-70: color('chill-70');
|
||||
$chill-60: color('chill-60');
|
||||
$chill-50: color('chill-50');
|
||||
$chill-40: color('chill-40');
|
||||
$chill-30: color('chill-30');
|
||||
$chill-20: color('chill-20');
|
||||
$chill-10: color('chill-10');
|
||||
$chill-05: color('chill-05');
|
||||
|
||||
$olive-60: color('olive-60');
|
||||
$olive-50: color('olive-50');
|
||||
$olive-40: color('olive-40');
|
||||
$olive-30: color('olive-30');
|
||||
$olive-20: color('olive-20');
|
||||
$olive-10: color('olive-10');
|
||||
$olive-05: color('olive-05');
|
||||
|
||||
$papaya-60: color('papaya-60');
|
||||
$papaya-50: color('papaya-50');
|
||||
$papaya-40: color('papaya-40');
|
||||
$papaya-30: color('papaya-30');
|
||||
$papaya-20: color('papaya-20');
|
||||
$papaya-10: color('papaya-10');
|
||||
$papaya-05: color('papaya-05');
|
||||
|
||||
$green-60: color('green-60');
|
||||
$green-50: color('green-50');
|
||||
$green-40: color('green-40');
|
||||
$green-30: color('green-30');
|
||||
$green-20: color('green-20');
|
||||
$green-10: color('green-10');
|
||||
$green-05: color('green-05');
|
||||
|
||||
$cran-50: color('cran-50');
|
||||
|
||||
$brand-00: color('brand-00');
|
||||
$brand-01: color('brand-01');
|
||||
$accent-00: color('accent-00');
|
||||
$accent-01: color('accent-01');
|
||||
$accent-02: color('accent-02');
|
||||
@@ -1,9 +0,0 @@
|
||||
@mixin no-selection {
|
||||
-webkit-touch-callout: none; /* iOS Safari */
|
||||
-webkit-user-select: none; /* Safari */
|
||||
-khtml-user-select: none; /* Konqueror HTML */
|
||||
-moz-user-select: none; /* Old versions of Firefox */
|
||||
-ms-user-select: none; /* Internet Explorer/Edge */
|
||||
user-select: none; /* Non-prefixed version, currently
|
||||
supported by Chrome, Edge, Opera and Firefox */
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
@use 'baseColors' as *;
|
||||
@use 'semanticColors' as *;
|
||||
@use 'spacing' as *;
|
||||
@use 'surfaces' as *;
|
||||
@use 'spacing' as *;
|
||||
@use 'typography' as *;
|
||||
|
||||
// BaseColors
|
||||
:root {
|
||||
@each $name, $color in $colors {
|
||||
--#{"" + $name}: #{$color};
|
||||
}
|
||||
}
|
||||
|
||||
// SemanticColors
|
||||
// Write semantic CSS color variables to root
|
||||
// **NOTE**: Most variables do not need to be exposed as a CSS variable
|
||||
:root {
|
||||
// See def in semanticColors.scss
|
||||
--black-rgb-color: #{extract-rgb('metal-100')};
|
||||
}
|
||||
|
||||
// Spacing
|
||||
@each $name, $text-def in $spacing {
|
||||
$suffix: str-replace('' + $name, 'space-', '');
|
||||
|
||||
.#{'padding-' + $suffix} {
|
||||
@include padding($suffix)
|
||||
}
|
||||
}
|
||||
|
||||
// Surfaces
|
||||
@each $name, $def in $shadow {
|
||||
$suffix: str-replace('' + $name, 'shadow-', '');
|
||||
|
||||
.#{'depth-' + $suffix} {
|
||||
@include depth($suffix)
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
.focused {
|
||||
@include focused;
|
||||
}
|
||||
}
|
||||
|
||||
// Typography
|
||||
// See typography.scss
|
||||
:root {
|
||||
--font-stack-sans: #{$internal-font-stack-sans};
|
||||
--font-stack-mono: #{$internal-font-stack-mono};
|
||||
}
|
||||
|
||||
@each $name, $text-def in $text {
|
||||
.#{$name} {
|
||||
@include text(str-replace($name, 'text-', ''))
|
||||
}
|
||||
}
|
||||
|
||||
.text-mono-m {
|
||||
@include text-mono-m;
|
||||
}
|
||||
|
||||
.text-mono-s {
|
||||
@include text-mono-s;
|
||||
}
|
||||
|
||||
.line-height-normal {
|
||||
@include line-height-normal;
|
||||
}
|
||||
|
||||
.line-height-condensed {
|
||||
@include line-height-condensed;
|
||||
}
|
||||
|
||||
.line-height-tight {
|
||||
@include line-height-tight;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
@use '../baseColors' as *;
|
||||
|
||||
// Exposes $color, stripped of hyphens, as a JS variable when directly imported
|
||||
:export {
|
||||
@each $name, $color in $colors {
|
||||
#{str-replace("" + $name, '-', '')}: #{$color};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
@use '../spacing.scss' as *;
|
||||
|
||||
// Exposes $spacing, as a JS variable when directly imported
|
||||
:export {
|
||||
@each $name, $size in $spacing {
|
||||
#{$name}: #{$size};
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
@use '../surfaces.scss' as *;
|
||||
|
||||
// Exposes $shadow as a JS variable when directly imported
|
||||
:export {
|
||||
@each $name, $shadow in $shadow {
|
||||
#{$name}: #{$shadow};
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
@use '../typography.scss' as *;
|
||||
@use '../func.scss' as *;
|
||||
|
||||
// Exposes $text, as a JS variable when directly imported
|
||||
// This is the only way for JS to directly receive the exposed `.text-*` classes
|
||||
:export {
|
||||
@each $name, $text-def in $text {
|
||||
#{$name}: text(#{str-replace("" + $name, 'text-', '')})
|
||||
}
|
||||
|
||||
// TODO: Can this be improved?
|
||||
text-mono-m: text-mono-m;
|
||||
text-mono-s: text-mono-s;
|
||||
|
||||
line-height-normal: line-height-normal;
|
||||
line-height-condensed: line-height-condensed;
|
||||
line-height-tight: line-height-tight;
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Replace `$search` with `$replace` in `$string`
|
||||
* @author Hugo Giraudel
|
||||
* @param {String} $string - Initial string
|
||||
* @param {String} $search - Substring to replace
|
||||
* @param {String} $replace ('') - New value
|
||||
* @return {String} - Updated string
|
||||
*/
|
||||
// Taken from https://gist.github.com/PuddingNL/51866d4b9f1151963fbd973bf1d66116
|
||||
@use "sass:math";
|
||||
|
||||
@function str-replace($string, $search, $replace: '') {
|
||||
$index: str-index($string, $search);
|
||||
|
||||
@if $index {
|
||||
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
|
||||
}
|
||||
|
||||
@return $string;
|
||||
}
|
||||
|
||||
@function change-rem-unit-to-em($number) {
|
||||
@return math.div($number, 1rem) + 0em;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@forward 'baseColors';
|
||||
@forward 'semanticColors';
|
||||
@forward 'surfaces';
|
||||
@forward 'typography';
|
||||
@forward 'spacing';
|
||||
@@ -1,36 +0,0 @@
|
||||
@use 'baseColors' as *;
|
||||
@use 'func';
|
||||
|
||||
/**
|
||||
* Extracts RGB color channels from a named color definition
|
||||
*/
|
||||
@function extract-rgb($color-name: string) {
|
||||
$color: map-get($colors, $color-name);
|
||||
|
||||
@if $color {
|
||||
@return red($color), green($color), blue($color);
|
||||
}
|
||||
|
||||
@return null;
|
||||
}
|
||||
|
||||
// Provides raw black as a RGB number tuple for substitution into alpha modifying situations (shadows)
|
||||
// See exposed variable in export.scss
|
||||
$black-rgb-color: var(--black-rgb-color);
|
||||
|
||||
$control-border-color: $metal-30;
|
||||
// TODO: Find a better name
|
||||
$control-slight-color: $metal-10;
|
||||
$control-focus-color: $chill-40;
|
||||
|
||||
$button-blue-color: $chill-50;
|
||||
$button-blue-hover-color: $chill-60;
|
||||
$button-blue-push-color: $chill-70;
|
||||
|
||||
$button-white-color: $metal-00;
|
||||
$button-white-hover-color: $metal-05;
|
||||
$button-white-push-color: $metal-10;
|
||||
|
||||
$control-text-color-white: $metal-05;
|
||||
$control-text-color-dim: $metal-50;
|
||||
$control-text-color-black: $metal-90;
|
||||
@@ -1,26 +0,0 @@
|
||||
@use 'func' as *;
|
||||
|
||||
$_base-space: 1rem;
|
||||
|
||||
$spacing: (
|
||||
space-xs: 0.25 * $_base-space, // 4px
|
||||
space-s: 0.5 * $_base-space, // 8px
|
||||
|
||||
space-ms: 0.75 * $_base-space, // 12px
|
||||
space-m: 1 * $_base-space, // 16px
|
||||
space-ml: 1.25 * $_base-space, // 20px
|
||||
|
||||
space-l: 1.5 * $_base-space, // 24px
|
||||
space-xl: 2 * $_base-space, // 32px
|
||||
space-2xl: 2.5 * $_base-space, // 40px
|
||||
space-3xl: 3 * $_base-space, // 48px
|
||||
space-4xl: 4 * $_base-space, // 64px
|
||||
);
|
||||
|
||||
@function spacing($name: string) {
|
||||
@return map-get($spacing, "space-" + $name);
|
||||
}
|
||||
|
||||
@mixin padding($name: string) {
|
||||
padding: spacing($name);
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
@use 'semanticColors' as *;
|
||||
@use 'func' as *;
|
||||
|
||||
// --- Shadows
|
||||
|
||||
// TODO: Need better semantic names
|
||||
$shadow: (
|
||||
shadow-flat: none,
|
||||
shadow-slight: 0 1px 2px 0 rgba($black-rgb-color, 0.05),
|
||||
shadow-bordered: (0 1px 3px 0 rgba($black-rgb-color, 0.1), 0 1px 2px 0 rgba($black-rgb-color, 0.06)),
|
||||
shadow-3: (0 4px 6px -1px rgba($black-rgb-color, 0.1), 0 2px 4px -1px rgba($black-rgb-color, 0.06)),
|
||||
shadow-4: (0 10px 15px -3px rgba($black-rgb-color, 0.1), 0 4px 6px -2px rgba($black-rgb-color, 0.05)),
|
||||
shadow-popup: (0 20px 25px -5px rgba($black-rgb-color, 0.1), 0 10px 10px -5px rgba($black-rgb-color, 0.04)),
|
||||
shadow-6: (0 25px 50px -12px rgba($black-rgb-color, 0.25)),
|
||||
shadow-inset-slight: inset 0 2px 4px 0 rgba($black-rgb-color, 0.06),
|
||||
shadow-inset-well: inset 0 3px 5px 0 rgba($black-rgb-color, 0.1),
|
||||
);
|
||||
|
||||
// $shadow-outline: 0 0 0 3px rgba(66, 153, 225, 0.5);
|
||||
|
||||
$button-radius: 0.5rem; // 8px
|
||||
|
||||
@function shadow($name: string) {
|
||||
@return map-get($shadow, "shadow-" + $name);
|
||||
}
|
||||
|
||||
@mixin depth($name: string) {
|
||||
box-shadow: shadow($name);
|
||||
}
|
||||
|
||||
@mixin focused {
|
||||
&::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
|
||||
border: 2px solid $control-focus-color;
|
||||
border-radius: $button-radius;
|
||||
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
@use 'func' as *;
|
||||
|
||||
// --- Font Families
|
||||
|
||||
/**
|
||||
* Do not directly reference. Use the $font-stack-sans and $font-stack-mono variables instead
|
||||
*/
|
||||
$internal-font-stack-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
|
||||
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
$internal-font-stack-mono: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
|
||||
// See export.scss
|
||||
$font-stack-sans: var(--font-stack-sans);
|
||||
$font-stack-mono: var(--font-stack-mono);
|
||||
|
||||
// --- Text Sizes/Scale
|
||||
// Chosen to produce integer sizes from a base font size of 16px
|
||||
|
||||
$text: (
|
||||
text-xs: (
|
||||
size: 0.5rem, // 8px
|
||||
),
|
||||
text-s: (
|
||||
size: 0.75rem, // 12px
|
||||
),
|
||||
text-ms: (
|
||||
size: 0.875rem, // 14px
|
||||
),
|
||||
text-m: (
|
||||
size: 1rem, // 16px
|
||||
weight: bolder,
|
||||
),
|
||||
text-ml: (
|
||||
size: 1.25rem, // 18px
|
||||
weight: bolder,
|
||||
),
|
||||
text-l: (
|
||||
size: 1.5rem, // 24px
|
||||
weight: bolder,
|
||||
),
|
||||
text-xl: (
|
||||
size: 2rem, // 32px
|
||||
weight: bolder,
|
||||
),
|
||||
text-2xl: (
|
||||
size: 2.5rem, // 40px
|
||||
weight: bolder,
|
||||
),
|
||||
text-3xl: (
|
||||
size: 3rem, // 48px
|
||||
weight: bolder,
|
||||
),
|
||||
text-4xl: (
|
||||
size: 4rem, // 64px
|
||||
weight: bolder,
|
||||
)
|
||||
);
|
||||
|
||||
$highlight-weight: 600;
|
||||
|
||||
@function text($name: string) {
|
||||
@return map-get(map-get($text, "text-" + #{$name}), size);
|
||||
}
|
||||
|
||||
// --- Line heights
|
||||
|
||||
$lh-tight: 1;
|
||||
$lh-condensed: 1.25;
|
||||
$lh-normal: 1.5;
|
||||
|
||||
// --- Mixins
|
||||
|
||||
@mixin _text-base {
|
||||
font-family: $font-stack-sans;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
// General text
|
||||
|
||||
@mixin text($name: string) {
|
||||
$text-def: map-get($text, "text-" + $name);
|
||||
$size: map-get($text-def, size);
|
||||
$weight: map-get($text-def, weight);
|
||||
|
||||
@include _text-base;
|
||||
@if $size {
|
||||
font-size: $size;
|
||||
}
|
||||
@if $weight {
|
||||
font-weight: $weight;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin text-mono-m {
|
||||
font-size: text(m);
|
||||
font-family: $font-stack-mono;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@mixin text-mono-s {
|
||||
font-size: text(s);
|
||||
font-family: $font-stack-mono;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
// Line heights
|
||||
|
||||
@mixin line-height-normal {
|
||||
line-height: $lh-normal;
|
||||
}
|
||||
|
||||
@mixin line-height-condensed {
|
||||
line-height: $lh-condensed;
|
||||
}
|
||||
|
||||
@mixin line-height-tight {
|
||||
line-height: $lh-tight;
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
/*
|
||||
* Global CSS values to wrap into the bundle. Should not be imported by dependants
|
||||
*/
|
||||
@use 'derived/export.scss';
|
||||
@use 'typography';
|
||||
|
||||
// probably should leave this for the consumer to set?
|
||||
body, html {
|
||||
font-size: typography.text(m);
|
||||
font-family: typography.$font-stack-sans;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/*
|
||||
* Base SCSS file for external SASS imports (all dependants should import from this file to use the SASS vars)
|
||||
*/
|
||||
|
||||
// css prefix for clarity
|
||||
@forward 'css/index';
|
||||
@@ -1,31 +0,0 @@
|
||||
/**
|
||||
* Draws the baseline and toplines for a DOM element
|
||||
*/
|
||||
.baseline {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
|
||||
top: 0.2em;
|
||||
background-color: rgba(red, 0.2);
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
|
||||
position: absolute;
|
||||
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
|
||||
bottom: 0.2em;
|
||||
left: 0;
|
||||
background-color: rgba(red, 0.2);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
.colorBlock {
|
||||
display: inline-block;
|
||||
height: 7rem;
|
||||
width: 7rem;
|
||||
|
||||
padding: 1.5rem;
|
||||
margin-right: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
@use 'baseColors' as *;
|
||||
|
||||
.cube {
|
||||
margin: 1rem;
|
||||
background-color: $brand-00;
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
.surface {
|
||||
display: inline-block;
|
||||
height: 12rem;
|
||||
width: 12rem;
|
||||
|
||||
padding: 1.5rem;
|
||||
margin-right: 4rem;
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
@use 'baseColors' as *;
|
||||
|
||||
.wrapper {
|
||||
background-color: $brand-00;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
import { UnifiedRunner } from '../unified-runner'
|
||||
|
||||
// @ts-ignore
|
||||
window.UnifiedRunner = UnifiedRunner
|
||||
@@ -1,8 +0,0 @@
|
||||
.react-devtools-fallback {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 70%;
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,4 +0,0 @@
|
||||
$cypress-blue: #3380FF;
|
||||
$cypress-gray: #f6f6f6;
|
||||
|
||||
$ct-accent-blue: #4299e1;
|
||||
@@ -1,23 +0,0 @@
|
||||
@forward './legacy-styles';
|
||||
@use './legacy-styles' as *;
|
||||
|
||||
$border-color: $metal-20;
|
||||
|
||||
$reporter-background-color: white;
|
||||
$spec-list-background-color: white;
|
||||
$left-nav-background-color: $metal-05;
|
||||
|
||||
$resizer-hover-color: $chill-40;
|
||||
|
||||
$aut-background-color: white;
|
||||
$aut-drop-shadow: shadow(bordered);
|
||||
|
||||
$runner-ct-header-height: 46px;
|
||||
|
||||
/**
|
||||
* Utility classes
|
||||
*/
|
||||
|
||||
.display-none {
|
||||
display: none !important;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
{
|
||||
"extends": "../ts/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
"target": "es2015",
|
||||
"module": "commonjs",
|
||||
/*
|
||||
* Allow javascript files to be compiled.
|
||||
* Override this in modules that need JS
|
||||
*/
|
||||
"allowJs": true,
|
||||
"jsx": "react",
|
||||
"noImplicitAny": false,
|
||||
"noImplicitThis": false,
|
||||
"preserveWatchOutput": true,
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
/* Generates corresponding '.d.ts' file. */
|
||||
// "declaration": true,
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
/* Generates corresponding '.map' file. */
|
||||
"sourceMap": true,
|
||||
/* Import emit helpers from 'tslib'. */
|
||||
"importHelpers": true,
|
||||
"strictNullChecks": true,
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
/* Strict Type-Checking Options */
|
||||
// "traceResolution": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
/**
|
||||
* Skip type checking of all declaration files (*.d.ts).
|
||||
* TODO: Look into changing this in the future
|
||||
*/
|
||||
/* Additional Checks */
|
||||
/* Report errors on unused locals. */
|
||||
// "noEmit": true,
|
||||
"noUnusedLocals": false,
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
/* Report error when not all code paths in function return a value. */
|
||||
"noImplicitReturns": true,
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "../", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": ["../driver/src"], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
"types": [], /* Type declaration files to be included in compilation. */
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"noErrorTruncation": true,
|
||||
"experimentalDecorators": true
|
||||
// "noResolve": true
|
||||
},
|
||||
"include": [
|
||||
"./lib/*.ts",
|
||||
"./src*.ts",
|
||||
"./src*.tsx",
|
||||
"./index.ts",
|
||||
"./index.d.ts",
|
||||
"./../ts/index.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"dist",
|
||||
"test"
|
||||
]
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
process.env.NO_LIVERELOAD = '1'
|
||||
|
||||
import _ from 'lodash'
|
||||
import path from 'path'
|
||||
import type webpack from 'webpack'
|
||||
import { getCommonConfig, getCopyWebpackPlugin } from '@packages/web-config/webpack.config.base'
|
||||
import * as cyIcons from '@packages/icons'
|
||||
|
||||
const commonConfig = getCommonConfig()
|
||||
const CopyWebpackPlugin = getCopyWebpackPlugin()
|
||||
|
||||
// @ts-ignore
|
||||
const babelLoader = _.find(commonConfig.module.rules, (rule) => {
|
||||
// @ts-ignore
|
||||
return _.includes(rule.use.loader, 'babel-loader')
|
||||
})
|
||||
|
||||
// @ts-ignore
|
||||
babelLoader.use.options.plugins.push([require.resolve('babel-plugin-prismjs'), {
|
||||
languages: ['javascript', 'coffeescript', 'typescript', 'jsx', 'tsx'],
|
||||
plugins: ['line-numbers', 'line-highlight'],
|
||||
theme: 'default',
|
||||
css: false,
|
||||
}])
|
||||
|
||||
const { pngRule, nonPngRules } = commonConfig!.module!.rules!.reduce<{
|
||||
nonPngRules: webpack.RuleSetRule[]
|
||||
pngRule: webpack.RuleSetRule | undefined
|
||||
}>((acc, rule) => {
|
||||
if (rule?.test?.toString().includes('png')) {
|
||||
return {
|
||||
...acc,
|
||||
pngRule: rule,
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
...acc,
|
||||
nonPngRules: [...acc.nonPngRules, rule],
|
||||
}
|
||||
}, {
|
||||
nonPngRules: [],
|
||||
pngRule: undefined,
|
||||
})
|
||||
|
||||
if (!pngRule || !pngRule.use) {
|
||||
throw Error('Could not find png loader')
|
||||
}
|
||||
|
||||
(pngRule.use as webpack.RuleSetLoader[])[0].options = {
|
||||
name: '[name].[ext]',
|
||||
outputPath: 'img',
|
||||
publicPath: '/__cypress/runner/img/',
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const config: webpack.Configuration = {
|
||||
...commonConfig,
|
||||
module: {
|
||||
rules: [
|
||||
...nonPngRules,
|
||||
pngRule,
|
||||
{
|
||||
test: /index\.js/,
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
entry: {
|
||||
cypress_runner: [path.resolve(__dirname, 'src/index.js')],
|
||||
},
|
||||
output: {
|
||||
path: path.resolve(__dirname, 'dist'),
|
||||
filename: '[name].js',
|
||||
chunkFilename: '[name].[chunkhash].js',
|
||||
},
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
config.plugins = [
|
||||
// @ts-ignore
|
||||
...config.plugins,
|
||||
new CopyWebpackPlugin([{
|
||||
// @ts-ignore // There's a race condition in how these types are generated.
|
||||
from: cyIcons.getPathToFavicon('favicon.ico'),
|
||||
}]),
|
||||
]
|
||||
|
||||
config.resolve = {
|
||||
...config.resolve,
|
||||
alias: {
|
||||
bluebird: require.resolve('bluebird'),
|
||||
lodash: require.resolve('lodash'),
|
||||
mobx: require.resolve('mobx'),
|
||||
'mobx-react': require.resolve('mobx-react'),
|
||||
react: require.resolve('react'),
|
||||
'react-dom': require.resolve('react-dom'),
|
||||
},
|
||||
}
|
||||
|
||||
export default config
|
||||
@@ -1,137 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"cypress",
|
||||
"@cypress/dev"
|
||||
],
|
||||
"extends": [
|
||||
"plugin:@cypress/dev/general",
|
||||
"plugin:@cypress/dev/tests",
|
||||
"plugin:@cypress/dev/react",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"../reporter/src/.eslintrc.json"
|
||||
],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"env": {
|
||||
"cypress/globals": true
|
||||
},
|
||||
"rules": {
|
||||
"react/display-name": "off",
|
||||
"react/function-component-definition": [
|
||||
"error",
|
||||
{
|
||||
"namedComponents": "arrow-function",
|
||||
"unnamedComponents": "arrow-function"
|
||||
}
|
||||
],
|
||||
"react/jsx-boolean-value": [
|
||||
"error",
|
||||
"always"
|
||||
],
|
||||
"react/jsx-closing-bracket-location": [
|
||||
"error",
|
||||
"line-aligned"
|
||||
],
|
||||
"react/jsx-closing-tag-location": "error",
|
||||
"react/jsx-curly-brace-presence": [
|
||||
"error",
|
||||
{
|
||||
"props": "never",
|
||||
"children": "never"
|
||||
}
|
||||
],
|
||||
"react/jsx-curly-newline": "error",
|
||||
"react/jsx-filename-extension": [
|
||||
"warn",
|
||||
{
|
||||
"extensions": [
|
||||
".js",
|
||||
".jsx",
|
||||
".tsx"
|
||||
]
|
||||
}
|
||||
],
|
||||
"react/jsx-first-prop-new-line": "error",
|
||||
"react/jsx-max-props-per-line": [
|
||||
"error",
|
||||
{
|
||||
"maximum": 1,
|
||||
"when": "multiline"
|
||||
}
|
||||
],
|
||||
"react/jsx-no-bind": [
|
||||
"error",
|
||||
{
|
||||
"ignoreDOMComponents": true
|
||||
}
|
||||
],
|
||||
"react/jsx-no-useless-fragment": "error",
|
||||
"react/jsx-one-expression-per-line": [
|
||||
"error",
|
||||
{
|
||||
"allow": "literal"
|
||||
}
|
||||
],
|
||||
"react/jsx-sort-props": [
|
||||
"error",
|
||||
{
|
||||
"callbacksLast": true,
|
||||
"ignoreCase": true,
|
||||
"noSortAlphabetically": true,
|
||||
"reservedFirst": true
|
||||
}
|
||||
],
|
||||
"react/jsx-tag-spacing": [
|
||||
"error",
|
||||
{
|
||||
"closingSlash": "never",
|
||||
"beforeSelfClosing": "always"
|
||||
}
|
||||
],
|
||||
"react/jsx-wrap-multilines": [
|
||||
"error",
|
||||
{
|
||||
"declaration": "parens-new-line",
|
||||
"assignment": "parens-new-line",
|
||||
"return": "parens-new-line",
|
||||
"arrow": "parens-new-line",
|
||||
"condition": "parens-new-line",
|
||||
"logical": "parens-new-line",
|
||||
"prop": "parens-new-line"
|
||||
}
|
||||
],
|
||||
"react/no-array-index-key": "error",
|
||||
"react/no-unescaped-entities": "off",
|
||||
"react/prop-types": "off",
|
||||
"quote-props": [
|
||||
"error",
|
||||
"as-needed"
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"lib/*"
|
||||
],
|
||||
"rules": {
|
||||
"no-console": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"**/*.json"
|
||||
],
|
||||
"rules": {
|
||||
"quotes": "off",
|
||||
"comma-dangle": "off"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": "*.tsx",
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"react/jsx-no-bind": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
# Runner Shared
|
||||
|
||||
This is an old package, deprecated in favor of `@packages/app`. It has two remaining responsibilities before it can be entirely removed:
|
||||
|
||||
1. Contains `dom.js`, which uses proprietary webpack loaders and cannot easily be imported with Vite (dev server in `@packages/app`). This is bundled via webpack in either `@packages/runner` or `@packages/runner-ct`. Once `dom.js` is free of webpack-specific loader code, we should move it to `@packages/app`.
|
||||
2. Contains UI code for Cypress Studio, which was marked as experimental in Cypress 9.x and won't be part of Cypress 10.x initially. It will return at a later date. Until then, the code will be here. It's not currently used in the app.
|
||||
@@ -1,34 +0,0 @@
|
||||
{
|
||||
"name": "@packages/runner-shared",
|
||||
"version": "0.0.0-development",
|
||||
"private": true,
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "yarn test-unit",
|
||||
"test-unit": "mocha --config test/.mocharc.json src/*.spec.* src/**/*.spec.* --exit"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@cypress/react-tooltip": "0.5.3",
|
||||
"@packages/driver": "0.0.0-development",
|
||||
"@packages/socket": "0.0.0-development",
|
||||
"@packages/web-config": "0.0.0-development",
|
||||
"@popperjs/core": "2.9.2",
|
||||
"ansi-to-html": "0.6.14",
|
||||
"chai": "4.2.0",
|
||||
"chai-enzyme": "1.0.0-beta.1",
|
||||
"classnames": "2.3.1",
|
||||
"enzyme": "3.11.0",
|
||||
"enzyme-adapter-react-16": "1.15.2",
|
||||
"lodash": "^4.17.21",
|
||||
"mobx": "5.15.4",
|
||||
"mobx-react": "6.1.8",
|
||||
"mocha": "7.0.1",
|
||||
"nanoid": "3.1.31",
|
||||
"react": "16.8.6",
|
||||
"react-dom": "16.8.6",
|
||||
"react-popper": "2.2.5",
|
||||
"react-shadow-dom-retarget-events": "1.0.11",
|
||||
"sinon": "7.5.0"
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './dom'
|
||||
|
||||
export * from './studio'
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 387 KiB |
@@ -1,5 +0,0 @@
|
||||
export * from './studio'
|
||||
|
||||
export * from './studio-modals'
|
||||
|
||||
export * from './studio-recorder'
|
||||
@@ -1,186 +0,0 @@
|
||||
import { observer } from 'mobx-react'
|
||||
import React, { Component } from 'react'
|
||||
import { Dialog } from '@reach/dialog'
|
||||
import VisuallyHidden from '@reach/visually-hidden'
|
||||
|
||||
import './studio-modals.scss'
|
||||
|
||||
@observer
|
||||
export class StudioInstructionsModal extends Component {
|
||||
render () {
|
||||
return (
|
||||
<Dialog
|
||||
className='studio-modal studio-instructions-modal'
|
||||
aria-label='Start Studio'
|
||||
isOpen={this.props.open}
|
||||
onDismiss={this.props.close}
|
||||
>
|
||||
<div className='body'>
|
||||
<h1 className='title'>
|
||||
<i className='fas fa-magic icon' />
|
||||
{' '}
|
||||
Studio
|
||||
{' '}
|
||||
<span className='beta'>BETA</span>
|
||||
</h1>
|
||||
<div className='content center'>
|
||||
<div className='text'>
|
||||
Generate and save commands directly to your test suite by interacting with your app as an end user would. Right click on an element to add an assertion. Studio will track events that generate the following commands:
|
||||
</div>
|
||||
<div className='text center-box'>
|
||||
<ul>
|
||||
<li>
|
||||
<pre>.check()</pre>
|
||||
</li>
|
||||
<li>
|
||||
<pre>.click()</pre>
|
||||
</li>
|
||||
<li>
|
||||
<pre>.select()</pre>
|
||||
</li>
|
||||
<li>
|
||||
<pre>.type()</pre>
|
||||
</li>
|
||||
<li>
|
||||
<pre>.uncheck()</pre>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div className='text'>
|
||||
This feature is currently in Beta and we will be adding more commands and abilities in the future. Your
|
||||
{' '}
|
||||
<a href='https://on.cypress.io/studio-beta' target='_blank' rel="noreferrer">feedback</a>
|
||||
{' '}
|
||||
will be highly influential to our team.
|
||||
</div>
|
||||
</div>
|
||||
<div className='controls'>
|
||||
<button className='cancel' onClick={this.props.close}>Close</button>
|
||||
</div>
|
||||
</div>
|
||||
<button className='close-button' onClick={this.props.close}>
|
||||
<VisuallyHidden>Close</VisuallyHidden>
|
||||
<span aria-hidden={true}>
|
||||
<i className='fas fa-times' />
|
||||
</span>
|
||||
</button>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@observer
|
||||
export class StudioInitModal extends Component {
|
||||
render () {
|
||||
return (
|
||||
<Dialog
|
||||
className='studio-modal studio-init-modal'
|
||||
aria-label='Start Studio'
|
||||
isOpen={this.props.eventManager.studioRecorder.initModalIsOpen}
|
||||
onDismiss={this._close}
|
||||
>
|
||||
<div className='body'>
|
||||
<h1 className='title'>
|
||||
<i className='fas fa-magic icon' />
|
||||
{' '}
|
||||
Studio
|
||||
{' '}
|
||||
<span className='beta'>BETA</span>
|
||||
</h1>
|
||||
<div className='gif'>
|
||||
<img src={require('../static/studio.gif')} alt='Studio' />
|
||||
</div>
|
||||
<div className='content center'>
|
||||
<div className='text'>
|
||||
Generate Cypress commands by interacting with your site as an end user would. Then, save these commands directly to your test file.
|
||||
</div>
|
||||
<button className='btn-main' onClick={this._start}>
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button className='close-button' onClick={this._close}>
|
||||
<VisuallyHidden>Close</VisuallyHidden>
|
||||
<span aria-hidden={true}>
|
||||
<i className='fas fa-times' />
|
||||
</span>
|
||||
</button>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
_close = () => {
|
||||
this.props.eventManager.studioRecorder.closeInitModal()
|
||||
this.props.eventManager.studioRecorder.clearRunnableIds()
|
||||
}
|
||||
|
||||
_start = () => this.props.eventManager.emit('studio:start')
|
||||
}
|
||||
|
||||
@observer
|
||||
export class StudioSaveModal extends Component {
|
||||
state = {
|
||||
name: '',
|
||||
}
|
||||
|
||||
render () {
|
||||
const { name } = this.state
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
className='studio-modal studio-save-modal'
|
||||
aria-label='Save New Test'
|
||||
isOpen={this.props.eventManager.studioRecorder.saveModalIsOpen}
|
||||
onDismiss={this.props.eventManager.studioRecorder.closeSaveModal}
|
||||
>
|
||||
<div className='body'>
|
||||
<h1 className='title'>
|
||||
<i className='fas fa-magic icon' />
|
||||
{' '}
|
||||
Save New Test
|
||||
</h1>
|
||||
<div className='content'>
|
||||
<form onSubmit={this._save}>
|
||||
<div className='text'>
|
||||
<label className='text-strong' htmlFor='testName'>Test Name</label>
|
||||
<input id='testName' type='text' value={name} required={true} onChange={this._onInputChange} />
|
||||
</div>
|
||||
<div className='center'>
|
||||
<button className='btn-main' type='submit' disabled={!name}>
|
||||
Save Test
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<button className='close-button' onClick={this.props.eventManager.studioRecorder.closeSaveModal}>
|
||||
<VisuallyHidden>Close</VisuallyHidden>
|
||||
<span aria-hidden={true}>
|
||||
<i className='fas fa-times' />
|
||||
</span>
|
||||
</button>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
_onInputChange = (e) => {
|
||||
this.setState({ name: e.target.value })
|
||||
}
|
||||
|
||||
_save = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
const { name } = this.state
|
||||
|
||||
if (!name) return
|
||||
|
||||
this.props.eventManager.studioRecorder.save(name)
|
||||
}
|
||||
}
|
||||
|
||||
export const StudioModals = (props) => (
|
||||
<>
|
||||
<StudioInitModal eventManager={props.eventManager} />
|
||||
<StudioSaveModal eventManager={props.eventManager} />
|
||||
</>
|
||||
)
|
||||
@@ -1,141 +0,0 @@
|
||||
$font-sans: 'Mulish', 'Helvetica Neue', 'Arial', sans-serif;
|
||||
$open-sans: 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
|
||||
.studio-modal {
|
||||
max-width: 35em;
|
||||
|
||||
.body {
|
||||
font-family: $font-sans;
|
||||
margin-bottom: 2em;
|
||||
margin-top: -0.8em;
|
||||
|
||||
.title {
|
||||
color: #565554;
|
||||
font-family: $open-sans;
|
||||
font-weight: 600;
|
||||
padding: 0 1em;
|
||||
|
||||
.icon {
|
||||
color: #3386d4;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.beta {
|
||||
color: #959595;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.gif {
|
||||
margin: 15px 0;
|
||||
width: 100%;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
.text {
|
||||
color: #6c6c6c;
|
||||
padding: 0.5em 1em;
|
||||
|
||||
.text-strong {
|
||||
color: #565554;
|
||||
}
|
||||
|
||||
input {
|
||||
border: 1px solid #9d9ea9;
|
||||
border-radius: 2px;
|
||||
box-sizing: border-box;
|
||||
color: #6c6c6c;
|
||||
display: block;
|
||||
font-size: 16px;
|
||||
font-family: $font-sans;
|
||||
margin-top: 8px;
|
||||
padding: 4px;
|
||||
width: 100%;
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.center-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-main {
|
||||
background-color: #3386d4;
|
||||
border-radius: 0.25em;
|
||||
color: #fff;
|
||||
font-family: $font-sans;
|
||||
padding: 0.8em 4em;
|
||||
margin-top: 1em;
|
||||
|
||||
&:hover {
|
||||
background: darken(#3386d4, 10%);
|
||||
}
|
||||
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&[disabled],
|
||||
&[disabled]:hover,
|
||||
&[disabled]:active {
|
||||
background-color: #3386d4;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.close-button {
|
||||
color: #959595;
|
||||
}
|
||||
|
||||
&.studio-save-modal {
|
||||
max-width: 25em;
|
||||
min-width: 20em;
|
||||
|
||||
.body {
|
||||
margin-bottom: 1em;
|
||||
|
||||
.content .text {
|
||||
border-top: 1px solid #e1e2e4;
|
||||
font-size: 16px;
|
||||
margin-top: 0.8em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.studio-instructions-modal {
|
||||
.body {
|
||||
margin-bottom: 0;
|
||||
|
||||
.content {
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.2em;
|
||||
}
|
||||
|
||||
button {
|
||||
font-family: $font-sans;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,157 +0,0 @@
|
||||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
import sinon from 'sinon'
|
||||
import { Dialog } from '@reach/dialog'
|
||||
|
||||
import { createEventManager } from '../../test/utils'
|
||||
import { StudioModals, StudioInstructionsModal, StudioInitModal, StudioSaveModal } from './studio-modals'
|
||||
|
||||
describe('<StudioModals />', () => {
|
||||
let eventManager
|
||||
|
||||
beforeEach(() => {
|
||||
eventManager = createEventManager()
|
||||
sinon.stub(eventManager, 'emit')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
eventManager.studioRecorder.cancel()
|
||||
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
it('renders init and save modals', () => {
|
||||
const component = shallow(<StudioModals eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(StudioInitModal)).to.exist
|
||||
expect(component.find(StudioSaveModal)).to.exist
|
||||
})
|
||||
|
||||
describe('<StudioInstructionsModal />', () => {
|
||||
it('passes open prop to dialog', () => {
|
||||
const component = shallow(<StudioInstructionsModal open={false} close={sinon.stub()} />)
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
|
||||
component.setProps({ open: true })
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', true)
|
||||
})
|
||||
|
||||
it('calls close prop on close', () => {
|
||||
const close = sinon.stub()
|
||||
const component = shallow(<StudioInstructionsModal open={true} close={close} />)
|
||||
|
||||
component.find('.close-button').simulate('click')
|
||||
|
||||
expect(close).to.be.called
|
||||
})
|
||||
})
|
||||
|
||||
describe('<StudioInitModal />', () => {
|
||||
it('is not open by default', () => {
|
||||
const component = shallow(<StudioInitModal eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
})
|
||||
|
||||
it('is open and closes with studio recorder variable', () => {
|
||||
eventManager.studioRecorder.initModalIsOpen = true
|
||||
const component = shallow(<StudioInitModal eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', true)
|
||||
|
||||
eventManager.studioRecorder.closeInitModal()
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
})
|
||||
|
||||
it('closes and clears studio runnable ids when close is clicked', () => {
|
||||
sinon.stub(eventManager.studioRecorder, 'clearRunnableIds')
|
||||
eventManager.studioRecorder.initModalIsOpen = true
|
||||
const component = shallow(<StudioInitModal eventManager={eventManager} />)
|
||||
|
||||
component.find('.close-button').simulate('click')
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
expect(eventManager.studioRecorder.initModalIsOpen).to.equal(false)
|
||||
expect(eventManager.studioRecorder.clearRunnableIds).to.be.called
|
||||
})
|
||||
|
||||
it('emits studio:start when start button is clicked', () => {
|
||||
eventManager.studioRecorder.initModalIsOpen = true
|
||||
const component = shallow(<StudioInitModal eventManager={eventManager} />)
|
||||
|
||||
component.find('.btn-main').simulate('click')
|
||||
|
||||
expect(eventManager.emit).to.be.calledWith('studio:start')
|
||||
})
|
||||
})
|
||||
|
||||
describe('<StudioSaveModal />', () => {
|
||||
it('is not open by default', () => {
|
||||
const component = shallow(<StudioSaveModal eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
})
|
||||
|
||||
it('is open and closes with studio recorder variable', () => {
|
||||
eventManager.studioRecorder.saveModalIsOpen = true
|
||||
const component = shallow(<StudioSaveModal eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', true)
|
||||
|
||||
eventManager.studioRecorder.closeSaveModal()
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
})
|
||||
|
||||
it('closes when close is clicked', () => {
|
||||
eventManager.studioRecorder.saveModalIsOpen = true
|
||||
const component = shallow(<StudioSaveModal eventManager={eventManager} />)
|
||||
|
||||
component.find('.close-button').simulate('click')
|
||||
|
||||
expect(component.find(Dialog)).to.have.prop('isOpen', false)
|
||||
expect(eventManager.studioRecorder.saveModalIsOpen).to.equal(false)
|
||||
})
|
||||
|
||||
context('form', () => {
|
||||
beforeEach(() => {
|
||||
sinon.stub(eventManager.studioRecorder, 'save')
|
||||
|
||||
eventManager.studioRecorder.saveModalIsOpen = true
|
||||
})
|
||||
|
||||
it('updates input when typed into', () => {
|
||||
const component = shallow(<StudioSaveModal eventManager={eventManager} />)
|
||||
|
||||
component.find('input').simulate('change', { target: { value: 'my test name' } })
|
||||
|
||||
expect(component.find('input')).to.have.prop('value', 'my test name')
|
||||
})
|
||||
|
||||
it('calls studio recorder save with inputted text on submit', () => {
|
||||
const component = shallow(<StudioSaveModal eventManager={eventManager} />)
|
||||
|
||||
component.find('input').simulate('change', { target: { value: 'my test name' } })
|
||||
|
||||
expect(component.find('.btn-main')).to.have.prop('disabled', false)
|
||||
|
||||
component.find('form').simulate('submit', { preventDefault: () => {} })
|
||||
|
||||
expect(eventManager.studioRecorder.save).to.be.calledWith('my test name')
|
||||
})
|
||||
|
||||
it('disables form when there is no input', () => {
|
||||
const component = shallow(<StudioSaveModal eventManager={eventManager} />)
|
||||
|
||||
expect(component.find('.btn-main')).to.have.prop('disabled', true)
|
||||
|
||||
component.find('form').simulate('submit', { preventDefault: () => {} })
|
||||
|
||||
expect(eventManager.studioRecorder.save).not.to.be.called
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,139 +0,0 @@
|
||||
import React, { Component } from 'react'
|
||||
import { observer } from 'mobx-react'
|
||||
import Tooltip from '@cypress/react-tooltip'
|
||||
import cs from 'classnames'
|
||||
|
||||
import { StudioInstructionsModal } from './studio-modals'
|
||||
|
||||
@observer
|
||||
class Studio extends Component {
|
||||
state = {
|
||||
modalOpen: false,
|
||||
copySuccess: false,
|
||||
}
|
||||
|
||||
render () {
|
||||
const { model, hasUrl } = this.props
|
||||
const { modalOpen, copySuccess } = this.state
|
||||
|
||||
return (
|
||||
<div className='header-popup studio'>
|
||||
<StudioInstructionsModal open={modalOpen} close={this._closeModal} />
|
||||
<div className='text-block'>
|
||||
<span className={cs('icon', { 'is-active': model.isActive && !model.isFailed && hasUrl })}>
|
||||
<i className='fas' />
|
||||
</span>
|
||||
{' '}
|
||||
<span className='title'>Studio</span>
|
||||
{' '}
|
||||
<span className='beta'>Beta</span>
|
||||
</div>
|
||||
<div className='text-block'>
|
||||
<a href='#' className={cs('available-commands', { 'link-disabled': model.isLoading })} onClick={this._showModal}>Available Commands</a>
|
||||
</div>
|
||||
<div className='text-block'>
|
||||
<a href={!model.isLoading ? 'https://on.cypress.io/studio-beta' : undefined} target='_blank' className={cs('give-feedback', { 'link-disabled': model.isLoading })} rel="noreferrer">Give Feedback</a>
|
||||
</div>
|
||||
<div className='studio-controls'>
|
||||
<Tooltip
|
||||
title='Close Studio'
|
||||
className='cy-tooltip'
|
||||
visible={model.isLoading ? false : null}
|
||||
>
|
||||
<button
|
||||
className='header-button button-studio button-studio-close'
|
||||
disabled={model.isLoading}
|
||||
onClick={this._close}
|
||||
>
|
||||
<i className='fas fa-times' />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title='Restart'
|
||||
className='cy-tooltip'
|
||||
visible={model.isLoading ? false : null}
|
||||
>
|
||||
<button
|
||||
className='header-button button-studio button-studio-restart'
|
||||
disabled={model.isLoading}
|
||||
onClick={this._restart}
|
||||
>
|
||||
<i className='fas fa-undo' />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title={copySuccess ? 'Commands Copied!' : 'Copy Commands to Clipboard'}
|
||||
className='cy-tooltip'
|
||||
visible={model.isLoading || model.isEmpty ? false : null}
|
||||
updateCue={copySuccess}
|
||||
>
|
||||
<button
|
||||
className={cs('header-button button-studio button-studio-copy', {
|
||||
'button-success': copySuccess,
|
||||
})}
|
||||
disabled={model.isLoading || model.isEmpty}
|
||||
onClick={this._copy}
|
||||
onMouseLeave={this._endCopySuccess}
|
||||
>
|
||||
<i className={copySuccess ? 'fas fa-check' : 'fas fa-copy'} />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
title='Save Commands'
|
||||
className='cy-tooltip'
|
||||
visible={model.isLoading || model.isEmpty ? false : null}
|
||||
>
|
||||
<button
|
||||
className='header-button button-studio button-studio-save'
|
||||
disabled={model.isLoading || model.isEmpty}
|
||||
onClick={this._save}
|
||||
>
|
||||
<i className='fas fa-save' />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
_showModal = (e) => {
|
||||
e.preventDefault()
|
||||
|
||||
if (this.props.model.isLoading) return
|
||||
|
||||
this.setState({ modalOpen: true })
|
||||
}
|
||||
|
||||
_closeModal = () => {
|
||||
this.setState({ modalOpen: false })
|
||||
}
|
||||
|
||||
_close = () => {
|
||||
this.props.eventManager.emit('studio:cancel')
|
||||
}
|
||||
|
||||
_restart = () => {
|
||||
this.props.model.reset()
|
||||
this.props.eventManager.emit('restart')
|
||||
}
|
||||
|
||||
_copy = () => {
|
||||
if (this.state.copySuccess) return
|
||||
|
||||
this.props.eventManager.emit('studio:copy:to:clipboard', () => {
|
||||
this.setState({ copySuccess: true })
|
||||
})
|
||||
}
|
||||
|
||||
_save = () => {
|
||||
this.props.model.startSave()
|
||||
}
|
||||
|
||||
_endCopySuccess = () => {
|
||||
if (this.state.copySuccess) {
|
||||
this.setState({ copySuccess: false })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { Studio }
|
||||
@@ -1,156 +0,0 @@
|
||||
import React from 'react'
|
||||
import { shallow } from 'enzyme'
|
||||
import sinon from 'sinon'
|
||||
import Tooltip from '@cypress/react-tooltip'
|
||||
|
||||
import { Studio } from './studio'
|
||||
import { StudioInstructionsModal } from './studio-modals'
|
||||
import { createEventManager } from '../../test/utils'
|
||||
|
||||
const createModel = (props) => {
|
||||
return {
|
||||
isActive: false,
|
||||
isLoading: false,
|
||||
reset: sinon.stub(),
|
||||
startSave: sinon.stub(),
|
||||
...props,
|
||||
}
|
||||
}
|
||||
|
||||
describe('<Studio />', () => {
|
||||
let eventManager
|
||||
|
||||
beforeEach(() => {
|
||||
eventManager = createEventManager()
|
||||
})
|
||||
|
||||
context('icon', () => {
|
||||
it('is not active when studio is not active', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: false })} />)
|
||||
|
||||
expect(component.find('.icon')).not.to.have.className('is-active')
|
||||
})
|
||||
|
||||
it('is not active when there is no url', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} hasUrl={false} />)
|
||||
|
||||
expect(component.find('.icon')).not.to.have.className('is-active')
|
||||
})
|
||||
|
||||
it('is active when studio is active and there is a url', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} hasUrl={true} />)
|
||||
|
||||
expect(component.find('.icon')).to.have.className('is-active')
|
||||
})
|
||||
|
||||
it('is not active when test has failed', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true, isFailed: true })} hasUrl={true} />)
|
||||
|
||||
expect(component.find('.icon')).not.to.have.className('is-active')
|
||||
})
|
||||
})
|
||||
|
||||
context('header links', () => {
|
||||
it('does not show modal by default', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} />)
|
||||
|
||||
expect(component.find(StudioInstructionsModal)).to.have.prop('open', false)
|
||||
})
|
||||
|
||||
it('shows model when available commands is clicked', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} />)
|
||||
|
||||
component.find('.available-commands').simulate('click', { preventDefault: () => {} })
|
||||
|
||||
expect(component.find(StudioInstructionsModal)).to.have.prop('open', true)
|
||||
})
|
||||
|
||||
it('disables available commands link while loading', () => {
|
||||
const component = shallow(<Studio model={createModel({ isLoading: true })} />)
|
||||
|
||||
expect(component.find('.available-commands')).to.have.className('link-disabled')
|
||||
|
||||
component.find('.available-commands').simulate('click', { preventDefault: () => {} })
|
||||
|
||||
expect(component.find(StudioInstructionsModal)).to.have.prop('open', false)
|
||||
})
|
||||
|
||||
it('disables feedback link while loading', () => {
|
||||
const component = shallow(<Studio model={createModel({ isLoading: true })} />)
|
||||
|
||||
expect(component.find('.give-feedback')).to.have.className('link-disabled')
|
||||
expect(component.find('.give-feedback')).not.to.have.prop('href')
|
||||
})
|
||||
})
|
||||
|
||||
context('controls', () => {
|
||||
beforeEach(() => {
|
||||
sinon.stub(eventManager, 'emit')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
sinon.restore()
|
||||
})
|
||||
|
||||
it('disables all controls while studio is loading', () => {
|
||||
const component = shallow(<Studio model={createModel({ isLoading: true })} />)
|
||||
|
||||
expect(component.find('.button-studio-close')).to.have.prop('disabled', true)
|
||||
expect(component.find('.button-studio-restart')).to.have.prop('disabled', true)
|
||||
expect(component.find('.button-studio-save')).to.have.prop('disabled', true)
|
||||
})
|
||||
|
||||
it('renders tooltips', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(Tooltip).at(0)).to.have.prop('title', 'Close Studio')
|
||||
expect(component.find(Tooltip).at(1)).to.have.prop('title', 'Restart')
|
||||
expect(component.find(Tooltip).at(2)).to.have.prop('title', 'Copy Commands to Clipboard')
|
||||
expect(component.find(Tooltip).at(3)).to.have.prop('title', 'Save Commands')
|
||||
})
|
||||
|
||||
it('hides all tooltips while studio is loading', () => {
|
||||
const component = shallow(<Studio model={createModel({ isLoading: true })} eventManager={eventManager} />)
|
||||
|
||||
expect(component.find(Tooltip).at(0)).to.have.prop('visible', false)
|
||||
expect(component.find(Tooltip).at(1)).to.have.prop('visible', false)
|
||||
expect(component.find(Tooltip).at(2)).to.have.prop('visible', false)
|
||||
expect(component.find(Tooltip).at(3)).to.have.prop('visible', false)
|
||||
})
|
||||
|
||||
it('emits studio:cancel when close button is clicked', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} eventManager={eventManager} />)
|
||||
|
||||
component.find('.button-studio-close').simulate('click')
|
||||
|
||||
expect(eventManager.emit).to.be.calledWith('studio:cancel')
|
||||
})
|
||||
|
||||
it('resets studio recorder and emits restart when restart button is clicked', () => {
|
||||
const model = createModel({ isActive: true })
|
||||
const component = shallow(<Studio model={model} eventManager={eventManager} />)
|
||||
|
||||
component.find('.button-studio-restart').simulate('click')
|
||||
|
||||
expect(model.reset).to.be.called
|
||||
expect(eventManager.emit).to.be.calledWith('restart')
|
||||
})
|
||||
|
||||
it('starts copy to clipboard process when copy button is clicked', () => {
|
||||
const component = shallow(<Studio model={createModel({ isActive: true })} eventManager={eventManager} />)
|
||||
|
||||
component.find('.button-studio-copy').simulate('click')
|
||||
|
||||
expect(eventManager.emit).to.be.calledWith('studio:copy:to:clipboard')
|
||||
})
|
||||
|
||||
it('starts studio recorder saving when save button is clicked', () => {
|
||||
const model = createModel({ isActive: true })
|
||||
const component = shallow(<Studio model={model} eventManager={eventManager} />)
|
||||
|
||||
component.find('.button-studio-save').simulate('click')
|
||||
|
||||
expect(model.startSave).to.be.called
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
// This file is automatically generated.
|
||||
// Please do not change this file!
|
||||
interface CssExports {
|
||||
'specsList': string;
|
||||
}
|
||||
export const cssExports: CssExports;
|
||||
export default cssExports;
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"file": "test/helper.js",
|
||||
"require": "../web-config/node-register",
|
||||
"extension": "ts,jsx,tsx,js"
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
import { returnMockRequire, register } from '@packages/web-config/node-jsdom-setup'
|
||||
import 'regenerator-runtime/runtime'
|
||||
import sinon from 'sinon'
|
||||
|
||||
const driverMock = {}
|
||||
|
||||
register({
|
||||
enzyme: require('enzyme'),
|
||||
EnzymeAdapter: require('enzyme-adapter-react-16'),
|
||||
chaiEnzyme: require('chai-enzyme'),
|
||||
requireOverride (depPath) {
|
||||
if (depPath === '@packages/driver') {
|
||||
return driverMock
|
||||
}
|
||||
|
||||
// TODO: refactor w/ regex
|
||||
if (depPath.includes('.gif')) {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
returnMockRequire('@packages/socket/lib/browser', {
|
||||
client () {
|
||||
return { emit: () => {}, on: () => {} }
|
||||
},
|
||||
})
|
||||
|
||||
const _useFakeTimers = sinon.useFakeTimers
|
||||
let timers = []
|
||||
|
||||
sinon.useFakeTimers = function (...args) {
|
||||
const ret = _useFakeTimers.apply(this, args)
|
||||
|
||||
timers.push(ret)
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
driverMock.$ = sinon.stub().throws('$ called without being stubbed')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
timers.forEach((clock) => {
|
||||
return clock.restore()
|
||||
})
|
||||
|
||||
timers = []
|
||||
})
|
||||
@@ -1,21 +0,0 @@
|
||||
import $Cypress from '@packages/driver'
|
||||
import { EventManager } from '@packages/app/src/runner/event-manager'
|
||||
import type { Socket } from '@packages/socket/lib/browser'
|
||||
import { StudioRecorder } from '../src/studio'
|
||||
import * as MobX from 'mobx'
|
||||
|
||||
export const StubWebsocket = new Proxy<Socket>(Object.create(null), {
|
||||
get: (obj, prop) => {
|
||||
throw Error(`Cannot access ${String(prop)} on StubWebsocket!`)
|
||||
},
|
||||
})
|
||||
|
||||
export const createEventManager = () => {
|
||||
return new EventManager(
|
||||
$Cypress,
|
||||
MobX,
|
||||
{}, // TODO: Bring back "Cypress Studio" and integrate with 10.x runner // selectorPlaygroundModel
|
||||
StudioRecorder,
|
||||
StubWebsocket,
|
||||
)
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "../ts/tsconfig.dom.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react",
|
||||
"experimentalDecorators": true
|
||||
}
|
||||
}
|
||||
@@ -4,4 +4,6 @@ This is an old package, deprecated in favor of `@packages/app`. It has two remai
|
||||
|
||||
1. Bundles `@packages/reporter` and `@packages/driver` via webpack. Once those can be directly imported to `@packages/app`, we can remove this.
|
||||
2. Bundles styles for `@packages/reporter`, loaded in `main.scss`. Ideally, reporter should import its own styles.
|
||||
3. Some existing tests in `cypress/e2e` should be migrated to `@packages/app/cypress/e2e/runner`.
|
||||
3. Contains `dom.js`, which uses proprietary webpack loaders and cannot easily be imported with Vite (dev server in `@packages/app`). Once `dom.js` is free of webpack-specific loader code, we should move it to `@packages/app`.
|
||||
4. Contains Cypress Studio Recorder code, which was marked as experimental in Cypress 9.x and won't be part of Cypress 10.x initially. It will return at a later date. Until then, the code will be here. It's not currently used in the app. @see https://github.com/cypress-io/cypress/issues/22870
|
||||
5. Contains Legacy Cypress styles, most of these can likely be removed.
|
||||
|
||||
@@ -19,11 +19,9 @@
|
||||
"@fortawesome/fontawesome-free": "6.0.0",
|
||||
"@packages/driver": "0.0.0-development",
|
||||
"@packages/icons": "0.0.0-development",
|
||||
"@packages/network": "0.0.0-development",
|
||||
"@packages/reporter": "0.0.0-development",
|
||||
"@packages/rewriter": "0.0.0-development",
|
||||
"@packages/socket": "0.0.0-development",
|
||||
"@packages/web-config": "0.0.0-development",
|
||||
"@popperjs/core": "2.9.2",
|
||||
"babel-plugin-prismjs": "1.0.2",
|
||||
"bluebird": "3.5.3",
|
||||
"classnames": "2.3.1",
|
||||
@@ -36,6 +34,8 @@
|
||||
"prop-types": "15.7.2",
|
||||
"react": "16.8.6",
|
||||
"react-dom": "16.8.6",
|
||||
"react-popper": "2.2.5",
|
||||
"react-shadow-dom-retarget-events": "1.0.11",
|
||||
"rimraf": "3.0.2",
|
||||
"webpack": "^4.44.2",
|
||||
"webpack-cli": "3.3.2"
|
||||
|
||||
@@ -3,12 +3,12 @@ import retargetEvents from 'react-shadow-dom-retarget-events'
|
||||
|
||||
import $Cypress from '@packages/driver'
|
||||
import $dimensions from './dimensions'
|
||||
import { selectorPlaygroundHighlight } from './selector-playground/highlight'
|
||||
import { studioAssertionsMenu } from './studio/assertions-menu'
|
||||
import { selectorPlaygroundHighlight } from '../selector-playground/highlight'
|
||||
import { studioAssertionsMenu } from '../studio/assertions-menu'
|
||||
// The '!' tells webpack to disable normal loaders, and keep loaders with `enforce: 'pre'` and `enforce: 'post'`
|
||||
// This disables the CSSExtractWebpackPlugin and allows us to get the CSS as a raw string instead of saving it to a separate file.
|
||||
import selectorPlaygroundCSS from '!./selector-playground/selector-playground.scss'
|
||||
import studioAssertionsMenuCSS from '!./studio/assertions-menu.scss'
|
||||
import selectorPlaygroundCSS from '!../selector-playground/selector-playground.scss'
|
||||
import studioAssertionsMenuCSS from '!../studio/assertions-menu.scss'
|
||||
|
||||
const $ = $Cypress.$
|
||||
const styles = (styleString) => {
|
||||
1
packages/runner/src/dom/index.ts
Normal file
1
packages/runner/src/dom/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './dom'
|
||||
@@ -1,3 +1,3 @@
|
||||
import { UnifiedRunner } from '@packages/runner-ct/unified-runner'
|
||||
import { UnifiedRunner } from '../unified-runner'
|
||||
|
||||
window.UnifiedRunner = UnifiedRunner
|
||||
|
||||
5
packages/runner/src/studio/index.js
Normal file
5
packages/runner/src/studio/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
// Studio tests have been removed with v10 update.
|
||||
// You can find the tests in the PR below.
|
||||
// @see https://github.com/cypress-io/cypress/pull/9542
|
||||
|
||||
export * from './studio-recorder'
|
||||
@@ -1,14 +1,13 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import $Cypress from '@packages/driver'
|
||||
import {
|
||||
StudioRecorder,
|
||||
dom,
|
||||
} from '@packages/runner-shared'
|
||||
import { Reporter } from '@packages/reporter/src/main'
|
||||
import shortcuts from '@packages/reporter/src/lib/shortcuts'
|
||||
import * as MobX from 'mobx'
|
||||
|
||||
import { StudioRecorder } from './src/studio'
|
||||
import { dom } from './src/dom'
|
||||
|
||||
export const UnifiedRunner = {
|
||||
CypressJQuery: $Cypress.$,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user