Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: improve pkg/driver types #21197

Merged
merged 19 commits into from May 13, 2022
3 changes: 2 additions & 1 deletion packages/driver/src/cy/aliases.ts
@@ -1,4 +1,5 @@
import _ from 'lodash'
import type { $Cy } from '../cypress/cy'

import $errUtils from '../cypress/error_utils'

Expand All @@ -13,7 +14,7 @@ const aliasDisplayName = (name) => {
}

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (cy) => ({
export const create = (cy: $Cy) => ({
addAlias (ctx, aliasObj) {
const { alias, subject } = aliasObj

Expand Down
6 changes: 5 additions & 1 deletion packages/driver/src/cy/assertions.ts
Expand Up @@ -3,6 +3,8 @@ import Promise from 'bluebird'

import $dom from '../dom'
import $errUtils from '../cypress/error_utils'
import type { ICypress } from '../cypress'
import type { $Cy } from '../cypress/cy'

// TODO
// bTagOpen + bTagClosed
Expand Down Expand Up @@ -77,7 +79,7 @@ const parseValueActualAndExpected = (value, actual, expected) => {
return obj
}

export const create = (Cypress, cy) => {
export const create = (Cypress: ICypress, cy: $Cy) => {
const getUpcomingAssertions = () => {
const index = cy.state('index') + 1

Expand Down Expand Up @@ -347,6 +349,8 @@ export const create = (Cypress, cy) => {
if (_.isFunction(onRetry)) {
return cy.retry(onRetry, options)
}

return
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this trailing empty return? It looks very unusual to my eyes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's because TypeScript wants all return paths.

As the type of cy.retry became specific, TypeScript learned that this function returns a Promise above but nothing at the end.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without this it's an error.

}

// bail if we have no assertions and apply
Expand Down
16 changes: 9 additions & 7 deletions packages/driver/src/cy/chai.ts
Expand Up @@ -13,6 +13,8 @@ import $errUtils from '../cypress/error_utils'
import $stackUtils from '../cypress/stack_utils'
import $chaiJquery from '../cypress/chai_jquery'
import * as chaiInspect from './chai/inspect'
import type { StateFunc } from '../cypress/state'
import type { $Cy } from '../cypress/cy'

// all words between single quotes
const allPropertyWordsBetweenSingleQuotes = /('.*?')/g
Expand Down Expand Up @@ -210,7 +212,7 @@ chai.use((chai, u) => {
}
}

const overrideChaiAsserts = function (specWindow, state, assertFn) {
const overrideChaiAsserts = function (specWindow, state: StateFunc, assertFn) {
chai.Assertion.prototype.assert = createPatchedAssert(specWindow, state, assertFn)

const _origGetmessage = function (obj, args) {
Expand Down Expand Up @@ -437,7 +439,7 @@ chai.use((chai, u) => {
})
}

const captureUserInvocationStack = (specWindow, state, ssfi) => {
const captureUserInvocationStack = (specWindow, state: StateFunc, ssfi) => {
// we need a user invocation stack with the top line being the point where
// the error occurred for the sake of the code frame
// in chrome, stack lines from another frame don't appear in the
Expand All @@ -453,7 +455,7 @@ chai.use((chai, u) => {
state('currentAssertionUserInvocationStack', userInvocationStack)
}

const createPatchedAssert = (specWindow, state, assertFn) => {
const createPatchedAssert = (specWindow, state: StateFunc, assertFn) => {
return (function (...args) {
let err
const passed = chaiUtils.test(this, args as Chai.AssertionArgs)
Expand Down Expand Up @@ -491,7 +493,7 @@ chai.use((chai, u) => {
})
}

const overrideExpect = (specWindow, state) => {
const overrideExpect = (specWindow, state: StateFunc) => {
// only override assertions for this specific
// expect function instance so we do not affect
// the outside world
Expand All @@ -503,7 +505,7 @@ chai.use((chai, u) => {
}
}

const overrideAssert = function (specWindow, state) {
const overrideAssert = function (specWindow, state: StateFunc) {
const fn = (express, errmsg) => {
state('assertUsed', true)
captureUserInvocationStack(specWindow, state, fn)
Expand All @@ -525,7 +527,7 @@ chai.use((chai, u) => {
return fn
}

const setSpecWindowGlobals = function (specWindow, state) {
const setSpecWindowGlobals = function (specWindow, state: StateFunc) {
const expect = overrideExpect(specWindow, state)
const assert = overrideAssert(specWindow, state)

Expand All @@ -540,7 +542,7 @@ chai.use((chai, u) => {
}
}

create = function (specWindow, state, assertFn) {
create = function (specWindow: SpecWindow, state: StateFunc, assertFn: $Cy['assert']) {
restoreAsserts()

overrideChaiInspect()
Expand Down
3 changes: 2 additions & 1 deletion packages/driver/src/cy/commands/origin/index.ts
Expand Up @@ -8,6 +8,7 @@ import { preprocessConfig, preprocessEnv, syncConfigToCurrentOrigin, syncEnvToCu
import { $Location } from '../../../cypress/location'
import { LogUtils } from '../../../cypress/log'
import logGroup from '../../logGroup'
import type { StateFunc } from '../../../cypress/state'

const reHttp = /^https?:\/\//

Expand All @@ -22,7 +23,7 @@ const normalizeOrigin = (urlOrDomain) => {
return $Location.normalize(origin)
}

export default (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: Cypress.State, config: Cypress.InternalConfig) => {
export default (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: StateFunc, config: Cypress.InternalConfig) => {
let timeoutId

const communicator = Cypress.primaryOriginCommunicator
Expand Down
5 changes: 5 additions & 0 deletions packages/driver/src/cy/commands/xhr.ts
Expand Up @@ -60,6 +60,11 @@ const setRequest = (state, xhr, alias) => {
return state('requests', requests)
}

export interface XHRResponse {
xhr: any
alias: any
}

const setResponse = (state, xhr) => {
const obj = _.find(state('requests'), { xhr })

Expand Down
4 changes: 3 additions & 1 deletion packages/driver/src/cy/ensures.ts
Expand Up @@ -3,6 +3,8 @@ import $dom from '../dom'
import $utils from '../cypress/utils'
import $errUtils from '../cypress/error_utils'
import $elements from '../dom/elements'
import type { StateFunc } from '../cypress/state'
import type { $Cy } from '../cypress/cy'

const VALID_POSITIONS = 'topLeft top topRight left center right bottomLeft bottom bottomRight'.split(' ')

Expand All @@ -14,7 +16,7 @@ const VALID_POSITIONS = 'topLeft top topRight left center right bottomLeft botto

let returnFalse = () => false

export const create = (state, expect) => {
export const create = (state: StateFunc, expect: $Cy['expect']) => {
// TODO: we should probably normalize all subjects
// into an array and loop through each and verify
// each element in the array is valid. as it stands
Expand Down
3 changes: 2 additions & 1 deletion packages/driver/src/cy/focused.ts
Expand Up @@ -2,6 +2,7 @@ import $dom from '../dom'
import $window from '../dom/window'
import $elements from '../dom/elements'
import $actionability from './actionability'
import type { StateFunc } from '../cypress/state'

const simulateBlurEvent = (el, win) => {
// todo handle relatedTarget's per the spec
Expand Down Expand Up @@ -49,7 +50,7 @@ const simulateFocusEvent = (el, win) => {
}

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (state) => ({
export const create = (state: StateFunc) => ({
documentHasFocus () {
// hardcode document has focus as true
// since the test should assume the window
Expand Down
3 changes: 2 additions & 1 deletion packages/driver/src/cy/jquery.ts
Expand Up @@ -2,13 +2,14 @@ import $ from 'jquery'

import $dom from '../dom'
import $utils from '../cypress/utils'
import type { StateFunc } from '../cypress/state'

const remoteJQueryisNotSameAsGlobal = (remoteJQuery) => {
return remoteJQuery && (remoteJQuery !== $)
}

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (state) => ({
export const create = (state: StateFunc) => ({
$$ (selector, context) {
if (context == null) {
context = state('document')
Expand Down
3 changes: 2 additions & 1 deletion packages/driver/src/cy/location.ts
@@ -1,8 +1,9 @@
import { $Location } from '../cypress/location'
import type { StateFunc } from '../cypress/state'
import $utils from '../cypress/utils'

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (state) => ({
export const create = (state: StateFunc) => ({
getRemoteLocation (key?: string | undefined, win?: Window) {
try {
const remoteUrl = $utils.locToString(win ?? state('window'))
Expand Down
7 changes: 5 additions & 2 deletions packages/driver/src/cy/mouse.ts
Expand Up @@ -2,9 +2,12 @@ import $ from 'jquery'
import _ from 'lodash'
import $dom from '../dom'
import $elements from '../dom/elements'
import $Keyboard, { ModifiersEventOptions } from './keyboard'
import $Keyboard, { Keyboard, ModifiersEventOptions } from './keyboard'
import $selection from '../dom/selection'
import debugFn from 'debug'
import type { StateFunc } from '../cypress/state'
import type { IFocused } from './focused'
import type { ICypress } from '../cypress'

const debug = debugFn('cypress:driver:mouse')

Expand Down Expand Up @@ -47,7 +50,7 @@ type DefaultMouseOptions = ModifiersEventOptions & CoordsEventOptions & {
relatedTarget: HTMLElement | null
}

export const create = (state, keyboard, focused, Cypress) => {
export const create = (state: StateFunc, keyboard: Keyboard, focused: IFocused, Cypress: ICypress) => {
const isFirefox = Cypress.browser.family === 'firefox'

const sendPointerEvent = (el, evtOptions, evtName, bubbles = false, cancelable = false) => {
Expand Down
5 changes: 3 additions & 2 deletions packages/driver/src/cy/net-stubbing/add-command.ts
Expand Up @@ -27,6 +27,7 @@ import {
import { registerEvents } from './events'
import $errUtils from '../../cypress/error_utils'
import $utils from '../../cypress/utils'
import type { StateFunc } from '../../cypress/state'
import isValidDomain from 'is-valid-domain'
import isValidHostname from 'is-valid-hostname'

Expand Down Expand Up @@ -170,7 +171,7 @@ function validateRouteMatcherOptions (routeMatcher: RouteMatcherOptions): { isVa
return { isValid: true }
}

export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: Cypress.State) {
export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy, state: StateFunc) {
const { emitNetEvent } = registerEvents(Cypress, cy)

function addRoute (matcher: RouteMatcherOptions, handler?: RouteHandler) {
Expand Down Expand Up @@ -227,7 +228,7 @@ export function addCommand (Commands, Cypress: Cypress.Cypress, cy: Cypress.cy,
state('routes')[routeId] = {
log: Cypress.log(getRouteMatcherLogConfig(matcher, !!handler, alias, staticResponse)),
options: matcher,
handler,
handler: handler!,
hitCount: 0,
requests: {},
command: state('current'),
Expand Down
5 changes: 3 additions & 2 deletions packages/driver/src/cy/net-stubbing/aliasing.ts
Expand Up @@ -2,15 +2,16 @@ import _ from 'lodash'
import type {
Interception,
} from './types'
import type { StateFunc } from '../../cypress/state'

export function isDynamicAliasingPossible (state: Cypress.State) {
export function isDynamicAliasingPossible (state: StateFunc) {
// dynamic aliasing is possible if a route with dynamic interception has been defined
return _.find(state('routes'), (route) => {
return _.isFunction(route.handler)
})
}

export function getAliasedRequests (alias: string, state: Cypress.State): Interception[] {
export function getAliasedRequests (alias: string, state: StateFunc): Interception[] {
// Start with request-level (req.alias = '...') aliases that could be a match.
const requests = _.filter(state('aliasedRequests'), { alias })
.map(({ request }) => request)
Expand Down
3 changes: 2 additions & 1 deletion packages/driver/src/cy/net-stubbing/wait-for-route.ts
Expand Up @@ -3,10 +3,11 @@ import type {
InterceptionState,
} from './types'
import { getAliasedRequests } from './aliasing'
import type { StateFunc } from '../../cypress/state'

const RESPONSE_WAITED_STATES: InterceptionState[] = ['Complete', 'Errored']

export function waitForRoute (alias: string, state: Cypress.State, specifier: 'request' | 'response' | string): Interception | null {
export function waitForRoute (alias: string, state: StateFunc, specifier: 'request' | 'response' | string): Interception | null {
// 1. Create an array of known requests that have this alias.
const candidateRequests = getAliasedRequests(alias, state)

Expand Down
7 changes: 5 additions & 2 deletions packages/driver/src/cy/retries.ts
Expand Up @@ -3,12 +3,15 @@ import Promise from 'bluebird'

import $errUtils from '../cypress/error_utils'
import * as cors from '@packages/network/lib/cors'
import type { ICypress } from '../cypress'
import type { $Cy } from '../cypress/cy'
import type { StateFunc } from '../cypress/state'

const { errByPath, modifyErrMsg, throwErr, mergeErrProps } = $errUtils

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (Cypress, state, timeout, clearTimeout, whenStable, finishAssertions) => ({
retry (fn, options, log) {
export const create = (Cypress: ICypress, state: StateFunc, timeout: $Cy['timeout'], clearTimeout: $Cy['clearTimeout'], whenStable: $Cy['whenStable'], finishAssertions: (...args: any) => any) => ({
retry (fn, options, log?) {
// remove the runnables timeout because we are now in retry
// mode and should be handling timing out ourselves and dont
// want to accidentally time out via mocha
Expand Down
4 changes: 3 additions & 1 deletion packages/driver/src/cy/stability.ts
@@ -1,7 +1,9 @@
import Promise from 'bluebird'
import type { ICypress } from '../cypress'
import type { StateFunc } from '../cypress/state'

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (Cypress, state) => ({
export const create = (Cypress: ICypress, state: StateFunc) => ({
isStable: (stable: boolean = true, event: string) => {
if (state('isStable') === stable) {
return
Expand Down
9 changes: 5 additions & 4 deletions packages/driver/src/cy/timeouts.ts
@@ -1,9 +1,10 @@
import _ from 'lodash'
import $errUtils from '../cypress/error_utils'
import type { StateFunc } from '../cypress/state'

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (state) => ({
timeout (ms: number, delta: boolean = false) {
export const create = (state: StateFunc) => ({
timeout (ms?: number, delta: boolean = false) {
const runnable = state('runnable')

if (!runnable) {
Expand All @@ -13,8 +14,8 @@ export const create = (state) => ({
if (_.isFinite(ms)) {
// if delta is true then we add (or subtract) from the
// runnables current timeout instead of blanketingly setting it
ms = delta ? runnable.timeout() + ms : ms
runnable.timeout(ms)
ms = delta ? runnable.timeout() + ms! : ms
runnable.timeout(ms!)

return this
}
Expand Down
4 changes: 3 additions & 1 deletion packages/driver/src/cy/timers.ts
@@ -1,5 +1,7 @@
import type { ICypress } from '../cypress'

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (Cypress) => ({
export const create = (Cypress: ICypress) => ({
reset () {
return Cypress.action('app:timers:reset')
},
Expand Down
3 changes: 2 additions & 1 deletion packages/driver/src/cy/xhrs.ts
Expand Up @@ -2,6 +2,7 @@
import _ from 'lodash'

import $errUtils from '../cypress/error_utils'
import type { StateFunc } from '../cypress/state'

const validAliasApiRe = /^(\d+|all)$/

Expand All @@ -26,7 +27,7 @@ const xhrNotWaitedOnByIndex = (state, alias, index, prop) => {
}

// eslint-disable-next-line @cypress/dev/arrow-body-multiline-braces
export const create = (state) => ({
export const create = (state: StateFunc) => ({
getIndexedXhrByAlias (alias, index) {
let prop
let str
Expand Down