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: audit cross-origin related TODOs/FIXMEs #20975

Merged
merged 5 commits into from Apr 8, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions cli/types/cypress.d.ts
Expand Up @@ -1908,9 +1908,6 @@ declare namespace Cypress {
*/
origin(originOrDomain: string, fn: () => void): Chainable

// TODO: when we find other options to put into the 'data' argument of cy.origin, we may want to overload this type with
// a 'data' parameter that contains all data options, including args, and one that contains all data options, excluding args.
// This will provide better typings support for whatever args is set to as opposed to an optional undefined
Comment on lines -1911 to -1913
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding correct typings is part of the acceptance criteria of any feature work, so I felt this comment wasn't needed in the code. I put it in the issue for log: false, since that should be where we add an additional property to options.

/**
* Enables running Cypress commands in a secondary domain
* @see https://on.cypress.io/origin
Expand Down
@@ -1,3 +1,5 @@
const { assertLogLength } = require('../../../support/utils')

describe('cy.origin Cypress API', () => {
beforeEach(() => {
cy.visit('/fixtures/multi-domain.html')
Expand Down Expand Up @@ -189,28 +191,24 @@ describe('cy.origin Cypress API', () => {
})
})

// FIXME: convert to cypress-in-cypress tests once possible
it('log()', () => {
const logs: Cypress.Log[] = []

cy.on('log:added', (attrs, log: Cypress.Log) => {
logs.push(log)
})

cy.origin('http://foobar.com:3500', () => {
Cypress.log({
name: 'log',
message: 'test log',
})
})

// logs in the secondary origin, skips the primary driver, going through
// the runner to the reporter, so we have to break out of the AUT and
// test the actual command log.
// this is a bit convoluted since otherwise the test could falsely pass
// by finding its own log if we simply did `.contains('test log')`
cy.wrap(Cypress.$(window.top!.document.body))
.find('.reporter')
.contains('.runnable-title', 'log()')
.closest('.runnable')
.find('.runnable-commands-region .hook-item')
.eq(1)
.contains('.command-number', '2')
.closest('.command-wrapper-text')
.contains('test log')
.then(() => {
assertLogLength(logs, 3)
Copy link
Member

Choose a reason for hiding this comment

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

What should the first & the third log be?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cy.origin and (new url)

Screen Shot 2022-04-08 at 9 57 38 AM

expect(logs[1].get('name')).to.equal('log')
expect(logs[1].get('message')).to.equal('test log')
})
})
})

Expand Down
Expand Up @@ -152,7 +152,9 @@ describe('cy.origin', () => {
})

describe('errors', () => {
// TODO: Proper stack trace printing still needs to be addressed here
// TODO: Proper stack trace printing still needs to be addressed here
// with a cy-in-cy test
// https://github.com/cypress-io/cypress/issues/20973
it('propagates secondary origin errors to the primary that occur within the test', (done) => {
cy.on('fail', (err) => {
expect(err.message).to.include('variable is not defined')
Expand Down
@@ -1,7 +1,3 @@
// FIXME: sync thrown errors inside of cy.origin cause cross origin errors in firefox when using experimentalSessionSupport
// This is likely due to cypress being re declared while on a cross origin iframe before the application navigates back.
// To reproduce, just add "experimentalSessionSupport" = true into the describe block below

Comment on lines -1 to -4
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This seems to be an issue with multiple tests and not just this one, so they'll all needed to be evaluated as part of this issue.

describe('cy.origin - uncaught errors', () => {
beforeEach(() => {
cy.visit('/fixtures/multi-domain.html')
Expand Down Expand Up @@ -32,6 +28,7 @@ describe('cy.origin - uncaught errors', () => {
// TODO: we likely need to change the messaging around this error to make it clear to cy.origin users that
// this behavior is configurable with 'uncaught:exception', but it MUST be declared inside the cy.origin callback
// and that 'uncaught:exception' will NOT be triggered outside that callback (inside the primary origin)
// https://github.com/cypress-io/cypress/issues/20969
expect(err.name).to.eq('Error')
expect(err.message).to.include('sync error')
expect(err.message).to.include('The following error originated from your application code, not from Cypress.')
Expand Down
Expand Up @@ -21,6 +21,7 @@ describe('cy.origin', () => {
})

// TODO: $Location does not support ipv6
// https://github.com/cypress-io/cypress/issues/20970
it.skip('succeeds on an ipv6 address', () => {
cy.origin('0000:0000:0000:0000:0000:0000:0000:0001', () => undefined)
cy.then(() => {
Expand Down
Expand Up @@ -190,6 +190,7 @@ describe('navigation events', () => {
})

// TODO: this test should re revisited with the cypress in cypress tests available in 10.0
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// TODO: this test should re revisited with the cypress in cypress tests available in 10.0
// TODO: this test should revisited with the cypress in cypress tests available in 10.0

Copy link
Member

Choose a reason for hiding this comment

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

Any reason we can't add this test to the packages/runner tests? Those tests are running Cypress in Cypress in 9.x form what I can tell.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The multi-origin stuff doesn't really work with the isolated runner tests in 9.x due to there being another version of the driver in the spec bridge that's not currently taken into account in the isolated runner. It's not really worth adding the support for it in the isolated runner since it's being replaced in 10.0.

// https://github.com/cypress-io/cypress/issues/20973
it.skip('the runner url updates appropriately', () => {
cy.origin('http://foobar.com:3500', () => {
cy.get('a[data-cy="cross-origin-page"]').click()
Expand Down
4 changes: 3 additions & 1 deletion packages/driver/src/cy/commands/navigation.ts
Expand Up @@ -1129,7 +1129,9 @@ export default (Commands, Cypress, cy, state, config) => {
const existingAutOrigin = $Location.create(win.location.href).origin
const params = { remote, existing, previousUrlVisited: existingAutOrigin, log: options._log, isCrossOriginSpecBridge: true }

// TODO: need a better error message
// TODO: Need a better error message. We should mention using
// cy.origin in order to visit different origins.
// https://github.com/cypress-io/cypress/issues/20974
mschile marked this conversation as resolved.
Show resolved Hide resolved
return cannotVisitDifferentOrigin(params)
}

Expand Down
4 changes: 3 additions & 1 deletion packages/driver/src/cypress/cy.ts
Expand Up @@ -566,7 +566,9 @@ export class $Cy extends EventEmitter2 implements ITimeouts, IStability, IAssert
// we failed setting the remote window props which
// means the page navigated to a different origin

// With cross origin support this is an expected error that may or may not be bad, we will rely on the page load timeout to throw if we don't end up where we expect to be.
// With cross-origin support, this is an expected error that may or may
// not be bad, we will rely on the page load timeout to throw if we
// don't end up where we expect to be.
if (this.config('experimentalLoginFlows') && err.name === 'SecurityError') {
return
}
Expand Down
3 changes: 1 addition & 2 deletions packages/driver/src/multi-domain/cypress.ts
Expand Up @@ -104,6 +104,7 @@ const onBeforeAppWindowLoad = (Cypress: Cypress.Cypress, cy: $Cy) => (autWindow:
}

// TODO: DRY this up with the mostly-the-same code in src/cypress/cy.js
// https://github.com/cypress-io/cypress/issues/20972
bindToListeners(autWindow, {
onError: handleErrorEvent(cy, 'app'),
onHistoryNav () {},
Expand Down Expand Up @@ -149,8 +150,6 @@ const onBeforeAppWindowLoad = (Cypress: Cypress.Cypress, cy: $Cy) => (autWindow:

return Cypress.action('app:window:unload', e)
},
// TODO: this currently only works on hashchange, but needs work
// for other navigation events
Comment on lines -152 to -153
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This work has been done, so this comment was outdated.

onNavigation (...args) {
return Cypress.action('app:navigation:changed', ...args)
},
Expand Down
6 changes: 4 additions & 2 deletions packages/driver/src/multi-domain/domain_fn.ts
Expand Up @@ -77,8 +77,10 @@ export const handleOriginFn = (Cypress: Cypress.Cypress, cy: $Cy) => {
}

const setRunnableStateToPassed = () => {
// TODO: We're telling the runnable that it has passed to avoid a timeout on the last (empty) command. Normally this would be set inherently by running (runnable.run) the test.
// Set this to passed regardless of the state of the test, the runnable isn't responsible for reporting success.
// HACK: We're telling the runnable that it has passed to avoid a timeout
// on the last (empty) command. Normally this would be set inherently by
// running runnable.run() the test. Set this to passed regardless of the
// state of the test, the runnable isn't responsible for reporting success.
Copy link
Member

Choose a reason for hiding this comment

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

what is responsible here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The runnable is the test itself, so it's passed or failed by everything in the test passing or something failing, be it a command or assertion or an error being thrown.

The runnable in the secondary driver is mostly stubbed out and its state doesn't influence the actual runnable in the primary driver.

It exists at all in the secondary driver because various parts of the driver rely on it having certain properties and methods. Ideally, it wouldn't need to exist in the secondary driver at all, but removing that would potentially mean a fairly broad refactor of the driver. For the sake of completing the experimental release and reducing the broader impact of the cross-origin support changes, we've not done that as of yet.

We plan to refactor and optimize the code that goes into the secondary driver, so we might be able to refactor out the need for the runnable in the secondary driver as part of that effort.

cy.state('runnable').state = 'passed'
}

Expand Down
10 changes: 0 additions & 10 deletions packages/driver/src/multi-domain/events/logs.ts
Expand Up @@ -2,20 +2,10 @@ import { LogUtils } from '../../cypress/log'

export const handleLogs = (Cypress: Cypress.Cypress) => {
const onLogAdded = (attrs) => {
// TODO:
// - handle printing console props (need to add to runner)
// this.runner.addLog(args[0], this.config('isInteractive'))

Cypress.specBridgeCommunicator.toPrimary('log:added', LogUtils.getDisplayProps(attrs))
}

const onLogChanged = (attrs) => {
// TODO:
// - add invocation stack if error:
// let parsedError = correctStackForCrossOriginError(log.get('err'), this.userInvocationStack)
// - notify runner? maybe not
// this.runner.addLog(args[0], this.config('isInteractive'))

Comment on lines -5 to -18
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should all be covered in this PR.

Cypress.specBridgeCommunicator.toPrimary('log:changed', LogUtils.getDisplayProps(attrs))
}

Expand Down
1 change: 0 additions & 1 deletion packages/driver/src/multi-domain/events/misc.ts
Expand Up @@ -9,7 +9,6 @@ export const handleMiscEvents = (Cypress: Cypress.Cypress, cy: $Cy) => {
Cypress.specBridgeCommunicator.toPrimary('viewport:changed', viewport)
})

// TODO: Should state syncing be built into cy.state instead of being explicitly called?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Decided we're not going to do this in a team discussion.

Cypress.specBridgeCommunicator.on('sync:state', (state) => {
cy.state(state)
})
Expand Down
1 change: 1 addition & 0 deletions packages/web-config/webpack.config.base.ts
Expand Up @@ -267,6 +267,7 @@ export const getSimpleConfig = () => ({
// packages/driver/src/cypress/source_map_utils.js when creating
// the cross origin bundle. for now, this is necessary so the build
// doesn't fail
// https://github.com/cypress-io/cypress/issues/19888
{
test: /\.wasm$/,
type: 'javascript/auto',
Expand Down
4 changes: 3 additions & 1 deletion system-tests/test/multi_domain_error_spec.ts
Expand Up @@ -11,6 +11,8 @@ const onServer = function (app) {
})
}

// TODO: This is probably more appropriate for a cy-in-cy test
// https://github.com/cypress-io/cypress/issues/20973
describe('e2e cy.origin errors', () => {
systemTests.setup({
servers: [{
Expand Down Expand Up @@ -39,7 +41,7 @@ describe('e2e cy.origin errors', () => {
expect(res.stdout).to.contain('AssertionError')
expect(res.stdout).to.contain('Timed out retrying after 1000ms: Expected to find element: `#doesnotexist`, but never found it.')

// check to make sure the snapshot contains the 'cy.origin' sourcemap. TODO: This is probably more appropriate for a cy-in-cy test
// check to make sure the snapshot contains the 'cy.origin' sourcemap
expect(res.stdout).to.contain('http://localhost:3500/__cypress/tests?p=cypress/integration/multi_domain_error_spec.ts:102:12')
},
})
Expand Down
5 changes: 2 additions & 3 deletions system-tests/test/navigation_spec.ts
Expand Up @@ -7,8 +7,6 @@ const onServer = function (app) {
})
}

// FIXME: This partially solves https://github.com/cypress-io/cypress/issues/19632 but only when "experimentalLoginFlows" is false.
// TODO: This will be further solved by https://github.com/cypress-io/cypress/issues/20428
describe('e2e cross origin navigation', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was handled in this PR.

systemTests.setup({
servers: [{
Expand All @@ -22,7 +20,8 @@ describe('e2e cross origin navigation', () => {
},
})

// FIXME: add test that supports this for firefox
// TODO: convert to cypress-in-cypress test if possible
// https://github.com/cypress-io/cypress/issues/20973
systemTests.it('captures cross origin failures when "experimentalLoginFlows" config value is falsy', {
// keep the port the same to prevent issues with the snapshot
port: PORT,
Expand Down