mirror of
https://github.com/cypress-io/cypress.git
synced 2026-02-22 15:11:00 -06:00
move from driver/cypress/integration to driver/cypress/e2e
This commit is contained in:
@@ -20,7 +20,7 @@ function getFileContents (subject) {
|
||||
describe('src/cy/commands/actions/selectFile', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/fixtures/files-form.html')
|
||||
cy.wrap(Buffer.from('foo')).as('foo')
|
||||
cy.wrap(Cypress.Buffer.from('foo')).as('foo')
|
||||
})
|
||||
|
||||
context('#selectFile', () => {
|
||||
@@ -32,7 +32,7 @@ describe('src/cy/commands/actions/selectFile', () => {
|
||||
.then((input) => {
|
||||
expect(input[0].files.length).to.eq(1)
|
||||
expect(input[0].files[0].name).to.eq('foo.txt')
|
||||
expect(input[0].files[0].type).to.eq('')
|
||||
expect(input[0].files[0].type).to.eq('text/plain')
|
||||
expect(input[0].files[0].lastModified).to.be.closeTo(Date.now(), 1000)
|
||||
})
|
||||
|
||||
@@ -50,10 +50,12 @@ describe('src/cy/commands/actions/selectFile', () => {
|
||||
contents: '@foo',
|
||||
fileName: 'foo.txt',
|
||||
}, {
|
||||
contents: Buffer.from('{"a":"bar"}'),
|
||||
contents: Cypress.Buffer.from('{"a":"bar"}'),
|
||||
fileName: 'bar.json',
|
||||
},
|
||||
Buffer.from('baz'),
|
||||
Cypress.Buffer.from('baz'),
|
||||
// 'baz' in ascii
|
||||
Uint8Array.from([98, 97, 122]),
|
||||
])
|
||||
|
||||
cy.get('#multiple')
|
||||
@@ -62,6 +64,7 @@ describe('src/cy/commands/actions/selectFile', () => {
|
||||
expect(input[0].files[0].name).to.eq('foo.txt')
|
||||
expect(input[0].files[1].name).to.eq('bar.json')
|
||||
expect(input[0].files[2].name).to.eq('')
|
||||
expect(input[0].files[3].name).to.eq('')
|
||||
})
|
||||
|
||||
cy.get('#multiple')
|
||||
@@ -70,6 +73,7 @@ describe('src/cy/commands/actions/selectFile', () => {
|
||||
expect(contents[0]).to.eq('foo')
|
||||
expect(contents[1]).to.eq('{"a":"bar"}')
|
||||
expect(contents[2]).to.eq('baz')
|
||||
expect(contents[3]).to.eq('baz')
|
||||
})
|
||||
})
|
||||
|
||||
@@ -251,6 +255,40 @@ describe('src/cy/commands/actions/selectFile', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('mime types', () => {
|
||||
it('uses empty string for unknown extensions', () => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: 'foo.barbaz' })
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].type).to.eq('')
|
||||
})
|
||||
})
|
||||
|
||||
it('works with several common extensions', () => {
|
||||
[
|
||||
['png', 'image/png'],
|
||||
['jpg', 'image/jpeg'],
|
||||
['zip', 'application/zip'],
|
||||
['yaml', 'text/yaml'],
|
||||
['json', 'application/json'],
|
||||
].forEach(([extension, mimeType]) => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: `foo.${extension}` })
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].type).to.eq(mimeType)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('allows users to specify a mimetype', () => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: 'foo.zip', mimeType: 'image/png' })
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].type).to.eq('image/png')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('errors', {
|
||||
defaultCommandTimeout: 50,
|
||||
}, () => {
|
||||
|
||||
@@ -3,8 +3,8 @@ describe('selector_playground', () => {
|
||||
cy.visit('/fixtures/dom.html')
|
||||
.then(() => {
|
||||
// We trick the selector-playground into rendering while the test is running
|
||||
top.UnifiedRunner.MobX.configure({ enforceActions: 'never' })
|
||||
top.__showSelectorPlaygroundForTestingPurposes()
|
||||
top.Runner.configureMobx({ enforceActions: 'never' })
|
||||
top.Runner.state.isRunning = false
|
||||
|
||||
const $highlightBtn = cy.$$('button.highlight-toggle:visible', top.document)
|
||||
|
||||
|
||||
@@ -1,713 +0,0 @@
|
||||
const { _, $ } = Cypress
|
||||
|
||||
// Reading and decoding files from an input element would, in the real world,
|
||||
// be handled by the application under test, and they would assert on their
|
||||
// application state. We want to assert on how selectFile behaves directly
|
||||
// though, and getting the files associated with an <input> as strings is
|
||||
// handy.
|
||||
function getFileContents (subject) {
|
||||
const decoder = new TextDecoder('utf8')
|
||||
|
||||
const fileContents = _.map(subject[0].files, (f) => {
|
||||
return f
|
||||
.arrayBuffer()
|
||||
.then((c) => decoder.decode(c))
|
||||
})
|
||||
|
||||
return Promise.all(fileContents)
|
||||
}
|
||||
|
||||
describe('src/cy/commands/actions/selectFile', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/fixtures/files-form.html')
|
||||
cy.wrap(Cypress.Buffer.from('foo')).as('foo')
|
||||
})
|
||||
|
||||
context('#selectFile', () => {
|
||||
it('selects a single file', () => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: 'foo.txt' })
|
||||
|
||||
cy.get('#basic')
|
||||
.then((input) => {
|
||||
expect(input[0].files.length).to.eq(1)
|
||||
expect(input[0].files[0].name).to.eq('foo.txt')
|
||||
expect(input[0].files[0].type).to.eq('text/plain')
|
||||
expect(input[0].files[0].lastModified).to.be.closeTo(Date.now(), 1000)
|
||||
})
|
||||
|
||||
cy.get('#basic')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foo')
|
||||
})
|
||||
})
|
||||
|
||||
it('selects multiple files', () => {
|
||||
cy.get('#multiple')
|
||||
.selectFile([
|
||||
{
|
||||
contents: '@foo',
|
||||
fileName: 'foo.txt',
|
||||
}, {
|
||||
contents: Cypress.Buffer.from('{"a":"bar"}'),
|
||||
fileName: 'bar.json',
|
||||
},
|
||||
Cypress.Buffer.from('baz'),
|
||||
// 'baz' in ascii
|
||||
Uint8Array.from([98, 97, 122]),
|
||||
])
|
||||
|
||||
cy.get('#multiple')
|
||||
.should('include.value', 'foo.txt')
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].name).to.eq('foo.txt')
|
||||
expect(input[0].files[1].name).to.eq('bar.json')
|
||||
expect(input[0].files[2].name).to.eq('')
|
||||
expect(input[0].files[3].name).to.eq('')
|
||||
})
|
||||
|
||||
cy.get('#multiple')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eq('foo')
|
||||
expect(contents[1]).to.eq('{"a":"bar"}')
|
||||
expect(contents[2]).to.eq('baz')
|
||||
expect(contents[3]).to.eq('baz')
|
||||
})
|
||||
})
|
||||
|
||||
it('allows custom lastModified', () => {
|
||||
cy.get('#basic').selectFile({
|
||||
contents: '@foo',
|
||||
lastModified: 1234,
|
||||
})
|
||||
|
||||
cy.get('#basic').then((input) => {
|
||||
expect(input[0].files[0].lastModified).to.eq(1234)
|
||||
})
|
||||
})
|
||||
|
||||
it('selects files with an input from a label', () => {
|
||||
cy.get('#basic-label').selectFile({ contents: '@foo' })
|
||||
|
||||
cy.get('#basic')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foo')
|
||||
})
|
||||
})
|
||||
|
||||
it('selects files with an input from a containing label', () => {
|
||||
cy.get('#containing-label').selectFile({ contents: '@foo' })
|
||||
|
||||
cy.get('#contained')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foo')
|
||||
})
|
||||
})
|
||||
|
||||
it('invokes change and input events on the input', (done) => {
|
||||
const $input = cy.$$('#basic')
|
||||
|
||||
$input.on('input', (e) => {
|
||||
const obj = _.pick(e.originalEvent, 'bubbles', 'cancelable', 'composed', 'target', 'type')
|
||||
|
||||
expect(obj).to.deep.eq({
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
composed: true,
|
||||
target: $input.get(0),
|
||||
type: 'input',
|
||||
})
|
||||
|
||||
$input.on('change', (e) => {
|
||||
const obj = _.pick(e.originalEvent, 'bubbles', 'cancelable', 'composed', 'target', 'type')
|
||||
|
||||
expect(obj).to.deep.eq({
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
composed: false,
|
||||
target: $input.get(0),
|
||||
type: 'change',
|
||||
})
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('bubbles events', (done) => {
|
||||
cy.window().then((win) => {
|
||||
$(win).on('input', () => {
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('invokes events on the input without changing subject when passed a label', (done) => {
|
||||
cy.$$('#basic-label').on('input', () => {
|
||||
throw new Error('shouldn\'t happen')
|
||||
})
|
||||
|
||||
cy.$$('#basic').on('input', () => {
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic-label').selectFile({ contents: '@foo' })
|
||||
.should('have.id', 'basic-label')
|
||||
})
|
||||
|
||||
it('can empty previously filled input', () => {
|
||||
cy.get('#basic').selectFile({ contents: '@foo' })
|
||||
cy.get('#basic').selectFile([])
|
||||
.then((input) => {
|
||||
expect(input[0].files.length).to.eq(0)
|
||||
})
|
||||
})
|
||||
|
||||
it('works with shadow DOMs', () => {
|
||||
cy.get('#shadow')
|
||||
.shadow()
|
||||
.find('input')
|
||||
.as('shadowInput')
|
||||
.selectFile('@foo')
|
||||
|
||||
cy.get('@shadowInput')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('shorthands', () => {
|
||||
const validJsonString = `{
|
||||
"foo": 1,
|
||||
"bar": {
|
||||
"baz": "cypress"
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
it('works with aliased strings', () => {
|
||||
cy.wrap('foobar').as('alias')
|
||||
|
||||
cy.get('#basic').selectFile('@alias')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foobar')
|
||||
})
|
||||
})
|
||||
|
||||
it('works with aliased objects', () => {
|
||||
cy.wrap({ foo: 'bar' }).as('alias')
|
||||
|
||||
cy.get('#basic').selectFile('@alias')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('{"foo":"bar"}')
|
||||
})
|
||||
})
|
||||
|
||||
it('works with aliased fixtures', () => {
|
||||
cy.fixture('valid.json').as('myFixture')
|
||||
|
||||
cy.get('#basic').selectFile('@myFixture')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
// Because json files are loaded as objects, they get reencoded before
|
||||
// being used, stripping spaces and newlines
|
||||
expect(contents[0]).to.eql('{"foo":1,"bar":{"baz":"cypress"}}')
|
||||
})
|
||||
})
|
||||
|
||||
// Because this is such an important recipe for users, it gets a separate test
|
||||
// even though readFile already has unit tests around reading files as buffers.
|
||||
it('works with files read with null encoding', () => {
|
||||
cy.readFile('cypress/fixtures/valid.json', { encoding: null }).as('myFile')
|
||||
|
||||
cy.get('#basic').selectFile('@myFile')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql(validJsonString)
|
||||
})
|
||||
})
|
||||
|
||||
it('works with passed in paths', () => {
|
||||
cy.get('#multiple').selectFile(['cypress/fixtures/valid.json', 'cypress/fixtures/app.js'])
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql(validJsonString)
|
||||
expect(contents[1]).to.eql('{ \'bar\' }\n')
|
||||
})
|
||||
|
||||
cy.get('#multiple')
|
||||
.should('include.value', 'valid.json')
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].name).to.eq('valid.json')
|
||||
expect(input[0].files[1].name).to.eq('app.js')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('mime types', () => {
|
||||
it('uses empty string for unknown extensions', () => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: 'foo.barbaz' })
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].type).to.eq('')
|
||||
})
|
||||
})
|
||||
|
||||
it('works with several common extensions', () => {
|
||||
[
|
||||
['png', 'image/png'],
|
||||
['jpg', 'image/jpeg'],
|
||||
['zip', 'application/zip'],
|
||||
['yaml', 'text/yaml'],
|
||||
['json', 'application/json'],
|
||||
].forEach(([extension, mimeType]) => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: `foo.${extension}` })
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].type).to.eq(mimeType)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
it('allows users to specify a mimetype', () => {
|
||||
cy.get('#basic')
|
||||
.selectFile({ contents: '@foo', fileName: 'foo.zip', mimeType: 'image/png' })
|
||||
.then((input) => {
|
||||
expect(input[0].files[0].type).to.eq('image/png')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('errors', {
|
||||
defaultCommandTimeout: 50,
|
||||
}, () => {
|
||||
it('is a child command', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('A child command must be chained after a parent because it operates on a previous subject.')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when non dom subject', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` failed because it requires a DOM element.')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.noop({}).selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when non-input subject', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only be called on an `<input type="file">` or a `<label for="fileInput">` pointing to or containing one. Your subject is: `<body>...</body>`')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('body').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when non-file input', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only be called on an `<input type="file">` or a `<label for="fileInput">` pointing to or containing one. Your subject is: `<input type="text" id="text-input">`')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#text-input').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when label for non-file input', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only be called on an `<input type="file">` or a `<label for="fileInput">` pointing to or containing one. Your subject is: `<label for="text-input" id="text-label">Text label</label>`')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#text-label').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when label without an attached input', function (done) {
|
||||
// Even though this label contains a file input, testing on real browsers confirms that clicking it
|
||||
// does *not* activate the contained input.
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only be called on an `<input type="file">` or a `<label for="fileInput">` pointing to or containing one. Your subject is: `<label for="nonexistent" id="nonexistent-label">...</label>`')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#nonexistent-label').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when subject is collection of elements', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only be called on a single element. Your subject contained')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('input[type="file"]').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('throws when no arguments given', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` must be passed a Buffer or an object with a non-null `contents` property as its 1st argument. You passed: `undefined`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile()
|
||||
})
|
||||
|
||||
it('throws when file is null', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` must be passed a Buffer or an object with a non-null `contents` property as its 1st argument. You passed: `null`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile(null)
|
||||
})
|
||||
|
||||
it('throws when single file.contents is null', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` must be passed a Buffer or an object with a non-null `contents` property as its 1st argument. You passed: `{"contents":null}`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile({ contents: null })
|
||||
})
|
||||
|
||||
it('throws when file is an unknown alias', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` could not find a registered alias for: `@unknown`.')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile('@unknown')
|
||||
})
|
||||
|
||||
it('throws when file is an alias for a DOM node', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only attach strings, Buffers or objects, while your alias `@body` resolved to: `<body>...</body>`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('body').as('body')
|
||||
cy.get('#basic').selectFile('@body')
|
||||
})
|
||||
|
||||
it('throws when file is an alias for null', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only attach strings, Buffers or objects, while your alias `@null` resolved to: `null`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.wrap(null).as('null')
|
||||
cy.get('#basic').selectFile('@null')
|
||||
})
|
||||
|
||||
it('throws with aliased intercepts', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` can only attach strings, Buffers or objects, while your alias `@postUser` resolved to: `null`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.intercept('POST', '/users', {}).as('postUser')
|
||||
cy.get('#basic').selectFile('@postUser')
|
||||
})
|
||||
|
||||
it('throws when any path does not exist', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile("this/file/doesNotExist.json")` failed because the file does not exist at the following path:')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile(['cypress/fixtures/valid.json', 'this/file/doesNotExist.json'])
|
||||
})
|
||||
|
||||
it('throws when any file\'s contents is undefined', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` must be passed an array of Buffers or objects with non-null `contents`. At files[1] you passed: `{}`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile([{ contents: '@foo' }, {}])
|
||||
})
|
||||
|
||||
it('throws on invalid action', function (done) {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` `action` can only be `select` or `drag-drop`. You passed: `foobar`.')
|
||||
expect(err.docsUrl).to.eq('https://on.cypress.io/selectfile')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile({ contents: '@foo' }, { action: 'foobar' })
|
||||
})
|
||||
})
|
||||
|
||||
/*
|
||||
* The tests around actionability are somewhat limited, since the functionality is thoroughly tested in the
|
||||
* `cy.trigger()` unit tests. We include a few tests directly on `cy.selectFile()` in order to ensure we're
|
||||
* using $actionability.verify() properly, but don't extensively exercise the logic within it here.
|
||||
*
|
||||
* See trigger_spec.js for the full actionability test suite.
|
||||
*/
|
||||
describe('actionability', {
|
||||
defaultCommandTimeout: 50,
|
||||
}, () => {
|
||||
it('selects files with a hidden input from a visible label', () => {
|
||||
cy.get('#hidden-label').selectFile({ contents: '@foo' })
|
||||
|
||||
cy.get('#hidden')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foo')
|
||||
})
|
||||
})
|
||||
|
||||
it('does not work on hidden inputs by default', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` failed because this element is not visible')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#hidden').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('can force on hidden inputs', () => {
|
||||
cy.get('#hidden').selectFile({ contents: '@foo' }, { force: true })
|
||||
})
|
||||
|
||||
it('does not work on covered inputs by default', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include(`\`<input id="covered" type="file">\`
|
||||
|
||||
is being covered by another element:
|
||||
|
||||
\`<div id="covering"></div>\``)
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#covered').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('can force on covered inputs', () => {
|
||||
cy.get('#covered').selectFile({ contents: '@foo' }, { force: true })
|
||||
})
|
||||
|
||||
it('does not work on disabled inputs by default', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` failed because this element is `disabled`')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#disabled-label').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('can force on disabled inputs', () => {
|
||||
cy.get('#disabled-label').selectFile({ contents: '@foo' }, { force: true })
|
||||
})
|
||||
|
||||
it('does not work on hidden labels by default', (done) => {
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`cy.selectFile()` failed because this element is not visible')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#hidden-basic-label').selectFile({ contents: '@foo' })
|
||||
})
|
||||
|
||||
it('can force on hidden labels', () => {
|
||||
cy.get('#hidden-basic-label').selectFile({ contents: '@foo' }, { force: true })
|
||||
})
|
||||
|
||||
it('can scroll to input', () => {
|
||||
const scrolled = []
|
||||
|
||||
cy.on('scrolled', ($el, type) => {
|
||||
scrolled.push(type)
|
||||
})
|
||||
|
||||
cy.get('#scroll').selectFile({ contents: '@foo' })
|
||||
.then(() => {
|
||||
expect(scrolled).not.to.be.empty
|
||||
})
|
||||
})
|
||||
|
||||
it('can scroll to label', () => {
|
||||
const scrolled = []
|
||||
|
||||
cy.on('scrolled', ($el, type) => {
|
||||
scrolled.push(type)
|
||||
})
|
||||
|
||||
cy.get('#scroll-label').selectFile({ contents: '@foo' })
|
||||
.then(() => {
|
||||
expect(scrolled).not.to.be.empty
|
||||
})
|
||||
})
|
||||
|
||||
it('does not scroll when forced', () => {
|
||||
const scrolled = []
|
||||
|
||||
cy.on('scrolled', ($el, type) => {
|
||||
scrolled.push(type)
|
||||
})
|
||||
|
||||
cy.get('#scroll-label').selectFile({ contents: '@foo' }, { force: true })
|
||||
.then(() => {
|
||||
expect(scrolled).to.be.empty
|
||||
})
|
||||
})
|
||||
|
||||
it('waits until input stops animating', {
|
||||
defaultCommandTimeout: 1000,
|
||||
}, () => {
|
||||
let retries = 0
|
||||
|
||||
cy.on('command:retry', (obj) => {
|
||||
retries += 1
|
||||
})
|
||||
|
||||
cy.stub(cy, 'ensureElementIsNotAnimating')
|
||||
.throws(new Error('animating!'))
|
||||
.onThirdCall().returns()
|
||||
|
||||
cy.get('#basic').selectFile({ contents: '@foo' }).then(() => {
|
||||
expect(retries).to.eq(3)
|
||||
expect(cy.ensureElementIsNotAnimating).to.be.calledThrice
|
||||
})
|
||||
})
|
||||
|
||||
it('can specify scrollBehavior in options', () => {
|
||||
cy.get('#scroll').then((el) => {
|
||||
cy.spy(el[0], 'scrollIntoView')
|
||||
})
|
||||
|
||||
cy.get('#scroll').selectFile({ contents: '@foo' }, { scrollBehavior: 'bottom' })
|
||||
|
||||
cy.get('#scroll').then((el) => {
|
||||
expect(el[0].scrollIntoView).to.be.calledWith({ block: 'end' })
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('drag-drop', () => {
|
||||
it('attaches a file to an input when targeted', () => {
|
||||
cy.get('#basic').selectFile({ contents: '@foo' }, { action: 'drag-drop' })
|
||||
|
||||
cy.get('#basic')
|
||||
.then(getFileContents)
|
||||
.then((contents) => {
|
||||
expect(contents[0]).to.eql('foo')
|
||||
})
|
||||
})
|
||||
|
||||
it('invokes change and input events on an input when dropped over', (done) => {
|
||||
const $input = cy.$$('#basic')
|
||||
|
||||
$input.on('input', (e) => {
|
||||
const obj = _.pick(e.originalEvent, 'bubbles', 'cancelable', 'composed', 'target', 'type')
|
||||
|
||||
expect(obj).to.deep.eq({
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
composed: true,
|
||||
target: $input.get(0),
|
||||
type: 'input',
|
||||
})
|
||||
|
||||
$input.on('change', (e) => {
|
||||
const obj = _.pick(e.originalEvent, 'bubbles', 'cancelable', 'composed', 'target', 'type')
|
||||
|
||||
expect(obj).to.deep.eq({
|
||||
bubbles: true,
|
||||
cancelable: false,
|
||||
composed: false,
|
||||
target: $input.get(0),
|
||||
type: 'change',
|
||||
})
|
||||
|
||||
done()
|
||||
})
|
||||
})
|
||||
|
||||
cy.get('#basic').selectFile({ contents: '@foo' }, { action: 'drag-drop' })
|
||||
})
|
||||
|
||||
it('does not follow labels to their inputs', () => {
|
||||
cy.get('#basic-label').selectFile({ contents: '@foo' }, { action: 'drag-drop' })
|
||||
|
||||
cy.get('#basic').then((input) => {
|
||||
expect(input[0].files.length).to.eql(0)
|
||||
})
|
||||
})
|
||||
|
||||
it('does not select multiple files with a single-file input', () => {
|
||||
cy.get('#basic').selectFile(['@foo', '@foo'], { action: 'drag-drop' })
|
||||
cy.get('#basic').then((input) => {
|
||||
expect(input[0].files.length).to.eql(0)
|
||||
})
|
||||
})
|
||||
|
||||
it('drops files onto any element and triggers events', (done) => {
|
||||
const $body = cy.$$('body')
|
||||
let events = []
|
||||
|
||||
$body.on('input', (e) => {
|
||||
throw new Error('should not trigger input')
|
||||
})
|
||||
|
||||
$body.on('change', (e) => {
|
||||
throw new Error('should not trigger change')
|
||||
})
|
||||
|
||||
$body.on('drag', (e) => events.push(e))
|
||||
$body.on('dragenter', (e) => events.push(e))
|
||||
$body.on('dragover', (e) => events.push(e))
|
||||
$body.on('drop', (e) => {
|
||||
events.push(e)
|
||||
expect(_.map(events, 'originalEvent.type')).to.deep.eql(['drag', 'dragenter', 'dragover', 'drop'])
|
||||
expect(_.every(events, ['originalEvent.bubbles', true])).to.be.true
|
||||
expect(_.every(events, ['originalEvent.cancelable', true])).to.be.true
|
||||
expect(_.every(events, ['originalEvent.composed', true])).to.be.true
|
||||
expect(_.every(events, ['originalEvent.target', $body[0]])).to.be.true
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('body').selectFile('@foo', { action: 'drag-drop' })
|
||||
})
|
||||
|
||||
it('includes an entry in `dataTransfer.types`', (done) => {
|
||||
cy.$$('#multiple').on('drop', (e) => {
|
||||
expect(e.originalEvent.dataTransfer.types).to.contain('Files')
|
||||
done()
|
||||
})
|
||||
|
||||
cy.get('#multiple').selectFile({ contents: '@foo' }, { action: 'drag-drop' })
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,78 +0,0 @@
|
||||
const {
|
||||
getBackendStaticResponse,
|
||||
} = require('../../../../src/cy/net-stubbing/static-response-utils')
|
||||
|
||||
describe('driver/src/cy/net-stubbing/static-response-utils', () => {
|
||||
describe('.getBackendStaticResponse', () => {
|
||||
describe('delay', () => {
|
||||
it('does not set delay when delayMS is not provided', () => {
|
||||
const staticResponse = getBackendStaticResponse({})
|
||||
|
||||
expect(staticResponse).to.not.have.property('delay')
|
||||
})
|
||||
|
||||
it('sets delay', () => {
|
||||
const staticResponse = getBackendStaticResponse({ delayMs: 200 })
|
||||
|
||||
expect(staticResponse).to.have.property('delay', 200)
|
||||
})
|
||||
})
|
||||
|
||||
describe('fixtures', () => {
|
||||
it('does not set fixtures data when fixtures string is not provided', () => {
|
||||
const staticResponse = getBackendStaticResponse({})
|
||||
|
||||
expect(staticResponse).to.not.have.property('fixtures')
|
||||
})
|
||||
|
||||
it('parses fixture string without file encoding', () => {
|
||||
const staticResponse = getBackendStaticResponse({ fixture: 'file.html' })
|
||||
|
||||
expect(staticResponse.fixture).to.deep.equal({
|
||||
filePath: 'file.html',
|
||||
encoding: undefined,
|
||||
})
|
||||
})
|
||||
|
||||
it('parses fixture string with file encoding', () => {
|
||||
const staticResponse = getBackendStaticResponse({ fixture: 'file.html,utf8' })
|
||||
|
||||
expect(staticResponse.fixture).to.deep.equal({
|
||||
filePath: 'file.html',
|
||||
encoding: 'utf8',
|
||||
})
|
||||
})
|
||||
|
||||
it('parses fixture string with file encoding set as null to indicate Buffer', () => {
|
||||
const staticResponse = getBackendStaticResponse({ fixture: 'file.html,null' })
|
||||
|
||||
expect(staticResponse.fixture).to.deep.equal({
|
||||
filePath: 'file.html',
|
||||
encoding: null,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('body', () => {
|
||||
it('does not set body when body is undefined', () => {
|
||||
const staticResponse = getBackendStaticResponse({})
|
||||
|
||||
expect(staticResponse).to.not.have.property('body')
|
||||
})
|
||||
|
||||
it('sets body when body is provided as a string', () => {
|
||||
const staticResponse = getBackendStaticResponse({ body: 'body' })
|
||||
|
||||
expect(staticResponse.body).to.eq('body')
|
||||
})
|
||||
|
||||
it('sets body when body is provided as a ArrayBuffer', () => {
|
||||
const buffer = new ArrayBuffer(8)
|
||||
const staticResponse = getBackendStaticResponse({ body: buffer })
|
||||
|
||||
expect(staticResponse.body).to.be.a('arraybuffer')
|
||||
expect(staticResponse.body).to.eq(buffer)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,480 +0,0 @@
|
||||
import { expect } from 'chai'
|
||||
|
||||
describe('Proxy Logging', () => {
|
||||
const { _ } = Cypress
|
||||
|
||||
const url = '/testFlag'
|
||||
const alias = 'aliasName'
|
||||
|
||||
function testFlag (expectStatus, expectInterceptions, setupFn, getFn) {
|
||||
return () => {
|
||||
setupFn()
|
||||
|
||||
let resolve
|
||||
const p = new Promise((_resolve) => resolve = _resolve)
|
||||
|
||||
function testLog (log) {
|
||||
expect(log.alias).to.eq(expectInterceptions.length ? alias : undefined)
|
||||
expect(log.renderProps).to.deep.include({
|
||||
interceptions: expectInterceptions,
|
||||
...(expectStatus ? { status: expectStatus } : {}),
|
||||
})
|
||||
|
||||
resolve()
|
||||
}
|
||||
|
||||
cy.then(() => {
|
||||
cy.on('log:changed', (log) => {
|
||||
if (['request', 'xhr'].includes(log.name)) {
|
||||
try {
|
||||
testLog(log)
|
||||
resolve()
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('assertions failed:', err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
getFn(url)
|
||||
}).then(() => p)
|
||||
|
||||
if (expectStatus) {
|
||||
cy.wait(`@${alias}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
context('request logging', () => {
|
||||
it('fetch log shows resource type, url, method, and status code and has expected snapshots and consoleProps', (done) => {
|
||||
fetch('/some-url')
|
||||
|
||||
// trigger: Cypress.Log() called
|
||||
cy.once('log:added', (log) => {
|
||||
expect(log.snapshots).to.be.undefined
|
||||
expect(log.displayName).to.eq('fetch')
|
||||
expect(log.renderProps).to.include({
|
||||
indicator: 'pending',
|
||||
message: 'GET /some-url',
|
||||
})
|
||||
|
||||
expect(log.consoleProps).to.include({
|
||||
Method: 'GET',
|
||||
'Resource Type': 'fetch',
|
||||
'Request went to origin?': 'yes',
|
||||
'URL': 'http://localhost:3500/some-url',
|
||||
})
|
||||
|
||||
// case depends on browser
|
||||
const refererKey = _.keys(log.consoleProps['Request Headers']).find((k) => k.toLowerCase() === 'referer') || 'referer'
|
||||
|
||||
expect(log.consoleProps['Request Headers']).to.include({
|
||||
[refererKey]: window.location.href,
|
||||
})
|
||||
|
||||
expect(log.consoleProps).to.not.have.property('Response Headers')
|
||||
expect(log.consoleProps).to.not.have.property('Matched `cy.intercept()`')
|
||||
|
||||
// trigger: .snapshot('request')
|
||||
cy.on('log:changed', (log) => {
|
||||
try {
|
||||
expect(log.snapshots.map((v) => v.name)).to.deep.eq(['request', 'response'])
|
||||
expect(log.consoleProps['Response Headers']).to.include({
|
||||
'x-powered-by': 'Express',
|
||||
})
|
||||
|
||||
expect(log.consoleProps).to.not.have.property('Matched `cy.intercept()`')
|
||||
expect(log.renderProps).to.include({
|
||||
indicator: 'bad',
|
||||
message: 'GET 404 /some-url',
|
||||
})
|
||||
|
||||
expect(Object.keys(log.consoleProps)).to.deep.eq(
|
||||
['Event', 'Resource Type', 'Method', 'URL', 'Request went to origin?', 'Request Headers', 'Response Status Code', 'Response Headers'],
|
||||
)
|
||||
|
||||
done()
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('assertion error, retrying', err)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// @see https://github.com/cypress-io/cypress/issues/17656
|
||||
it('xhr log has response body/status code', (done) => {
|
||||
cy.window()
|
||||
.then({ timeout: 10000 }, (win) => {
|
||||
cy.on('log:changed', (log) => {
|
||||
try {
|
||||
expect(log.snapshots.map((v) => v.name)).to.deep.eq(['request', 'response'])
|
||||
expect(log.consoleProps['Response Headers']).to.include({
|
||||
'x-powered-by': 'Express',
|
||||
})
|
||||
|
||||
expect(log.consoleProps['Response Body']).to.include('Cannot GET /some-url')
|
||||
expect(log.consoleProps['Response Status Code']).to.eq(404)
|
||||
|
||||
expect(log.renderProps).to.include({
|
||||
indicator: 'bad',
|
||||
message: 'GET 404 /some-url',
|
||||
})
|
||||
|
||||
expect(Object.keys(log.consoleProps)).to.deep.eq(
|
||||
['Event', 'Resource Type', 'Method', 'URL', 'Request went to origin?', 'XHR', 'groups', 'Request Headers', 'Response Status Code', 'Response Headers', 'Response Body'],
|
||||
)
|
||||
|
||||
done()
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('assertion error, retrying', err)
|
||||
}
|
||||
})
|
||||
|
||||
const xhr = new win.XMLHttpRequest()
|
||||
|
||||
xhr.open('GET', '/some-url')
|
||||
xhr.send()
|
||||
})
|
||||
})
|
||||
|
||||
it('does not log an unintercepted non-xhr/fetch request', (done) => {
|
||||
const img = new Image()
|
||||
const logs: any[] = []
|
||||
let imgLoaded = false
|
||||
|
||||
cy.on('log:added', (log) => {
|
||||
if (imgLoaded) return
|
||||
|
||||
logs.push(log)
|
||||
})
|
||||
|
||||
img.onload = () => {
|
||||
imgLoaded = true
|
||||
expect(logs).to.have.length(0)
|
||||
done()
|
||||
}
|
||||
|
||||
img.src = `/fixtures/media/cypress.png?${Date.now()}`
|
||||
})
|
||||
|
||||
context('with cy.intercept()', () => {
|
||||
it('shows non-xhr/fetch log if intercepted', (done) => {
|
||||
const src = `/fixtures/media/cypress.png?${Date.now()}`
|
||||
|
||||
cy.intercept('/fixtures/**/*.png*')
|
||||
.then(() => {
|
||||
cy.once('log:added', (log) => {
|
||||
expect(log.displayName).to.eq('image')
|
||||
expect(log.renderProps).to.include({
|
||||
indicator: 'pending',
|
||||
message: `GET ${src}`,
|
||||
})
|
||||
|
||||
done()
|
||||
})
|
||||
|
||||
const img = new Image()
|
||||
|
||||
img.src = src
|
||||
})
|
||||
})
|
||||
|
||||
it('shows cy.visit if intercepted', () => {
|
||||
cy.intercept('/fixtures/empty.html')
|
||||
.then(() => {
|
||||
// trigger: cy.visit()
|
||||
cy.once('log:added', (log) => {
|
||||
expect(log.name).to.eq('visit')
|
||||
// trigger: intercept Cypress.Log
|
||||
cy.once('log:added', (log) => {
|
||||
expect(log.displayName).to.eq('document')
|
||||
})
|
||||
})
|
||||
})
|
||||
.visit('/fixtures/empty.html')
|
||||
})
|
||||
|
||||
it('intercept log has consoleProps with intercept info', (done) => {
|
||||
cy.intercept('/some-url', 'stubbed response').as('alias')
|
||||
.then(() => {
|
||||
fetch('/some-url')
|
||||
})
|
||||
|
||||
cy.on('log:changed', (log) => {
|
||||
if (log.displayName !== 'fetch') return
|
||||
|
||||
try {
|
||||
expect(log.renderProps).to.deep.include({
|
||||
message: 'GET 200 /some-url',
|
||||
indicator: 'successful',
|
||||
status: undefined,
|
||||
interceptions: [{
|
||||
alias: 'alias',
|
||||
command: 'intercept',
|
||||
type: 'stub',
|
||||
}],
|
||||
})
|
||||
|
||||
expect(Object.keys(log.consoleProps)).to.deep.eq(
|
||||
['Event', 'Resource Type', 'Method', 'URL', 'Request went to origin?', 'Matched `cy.intercept()`', 'Request Headers', 'Response Status Code', 'Response Headers', 'Response Body'],
|
||||
)
|
||||
|
||||
const interceptProps = log.consoleProps['Matched `cy.intercept()`']
|
||||
|
||||
expect(interceptProps).to.deep.eq({
|
||||
Alias: 'alias',
|
||||
Request: {
|
||||
method: 'GET',
|
||||
url: 'http://localhost:3500/some-url',
|
||||
body: '',
|
||||
httpVersion: '1.1',
|
||||
responseTimeout: Cypress.config('responseTimeout'),
|
||||
headers: interceptProps.Request.headers,
|
||||
},
|
||||
Response: {
|
||||
body: 'stubbed response',
|
||||
statusCode: 200,
|
||||
url: 'http://localhost:3500/some-url',
|
||||
headers: interceptProps.Response.headers,
|
||||
},
|
||||
RouteMatcher: {
|
||||
url: '/some-url',
|
||||
},
|
||||
RouteHandler: 'stubbed response',
|
||||
'RouteHandler Type': 'StaticResponse stub',
|
||||
})
|
||||
|
||||
done()
|
||||
} catch (err) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('assertion failed:', err)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('works with forceNetworkError', () => {
|
||||
const logs: any[] = []
|
||||
|
||||
cy.on('log:added', (log) => {
|
||||
if (log.displayName === 'fetch') {
|
||||
logs.push(log)
|
||||
}
|
||||
})
|
||||
|
||||
cy.intercept('/foo', { forceNetworkError: true }).as('alias')
|
||||
.then(() => {
|
||||
return fetch('/foo')
|
||||
.catch(() => {})
|
||||
})
|
||||
.wrap(logs)
|
||||
.should((logs) => {
|
||||
// retries...
|
||||
expect(logs).to.have.length.greaterThan(0)
|
||||
|
||||
for (const log of logs) {
|
||||
expect(log.err).to.include({ name: 'Error' })
|
||||
expect(log.consoleProps['Error']).to.be.an('Error')
|
||||
expect(log.snapshots.map((v) => v.name)).to.deep.eq(['request', 'error'])
|
||||
expect(log.state).to.eq('failed')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
context('flags', () => {
|
||||
const testFlagFetch = (expectStatus, expectInterceptions, setupFn) => {
|
||||
return testFlag(expectStatus, expectInterceptions, setupFn, (url) => fetch(url))
|
||||
}
|
||||
|
||||
it('is unflagged when not intercepted', testFlagFetch(
|
||||
undefined,
|
||||
[],
|
||||
() => {},
|
||||
))
|
||||
|
||||
it('spied flagged as expected', testFlagFetch(
|
||||
undefined,
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'spy',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url).as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('spy function flagged as expected', testFlagFetch(
|
||||
undefined,
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'function',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url, () => {}).as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('stubbed flagged as expected', testFlagFetch(
|
||||
undefined,
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'stub',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url, 'stubbed response').as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('stubbed flagged as expected with req.reply', testFlagFetch(
|
||||
undefined,
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'function',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url, (req) => {
|
||||
req.headers.foo = 'bar'
|
||||
req.reply('stubby mc stub')
|
||||
}).as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('req modified flagged as expected', testFlagFetch(
|
||||
'req modified',
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'function',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url, (req) => {
|
||||
req.headers.foo = 'bar'
|
||||
}).as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('res modified flagged as expected', testFlagFetch(
|
||||
'res modified',
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'function',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url, (req) => {
|
||||
req.continue((res) => {
|
||||
res.headers.foo = 'bar'
|
||||
})
|
||||
}).as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('req + res modified flagged as expected', testFlagFetch(
|
||||
'req + res modified',
|
||||
[{
|
||||
command: 'intercept',
|
||||
alias,
|
||||
type: 'function',
|
||||
}],
|
||||
() => {
|
||||
cy.intercept(url, (req) => {
|
||||
req.headers.foo = 'bar'
|
||||
req.continue((res) => {
|
||||
res.headers.foo = 'bar'
|
||||
})
|
||||
}).as(alias)
|
||||
},
|
||||
))
|
||||
})
|
||||
})
|
||||
|
||||
context('with cy.route()', () => {
|
||||
context('flags', () => {
|
||||
let $XMLHttpRequest
|
||||
|
||||
const testFlagXhr = (expectStatus, expectInterceptions, setupFn) => {
|
||||
return testFlag(expectStatus, expectInterceptions, setupFn, (url) => {
|
||||
const xhr = new $XMLHttpRequest()
|
||||
|
||||
xhr.open('GET', url)
|
||||
xhr.send()
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
cy.window()
|
||||
.then(({ XMLHttpRequest }) => {
|
||||
$XMLHttpRequest = XMLHttpRequest
|
||||
})
|
||||
})
|
||||
|
||||
it('is unflagged when not routed', testFlagXhr(
|
||||
undefined,
|
||||
[],
|
||||
() => {},
|
||||
))
|
||||
|
||||
it('spied flagged as expected', testFlagXhr(
|
||||
undefined,
|
||||
[{
|
||||
command: 'route',
|
||||
alias,
|
||||
type: 'spy',
|
||||
}],
|
||||
() => {
|
||||
cy.server()
|
||||
cy.route(`${url}`).as(alias)
|
||||
},
|
||||
))
|
||||
|
||||
it('stubbed flagged as expected', testFlagXhr(
|
||||
undefined,
|
||||
[{
|
||||
command: 'route',
|
||||
alias,
|
||||
type: 'stub',
|
||||
}],
|
||||
() => {
|
||||
cy.server()
|
||||
cy.route(url, 'stubbed response').as(alias)
|
||||
},
|
||||
))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
context('Cypress.ProxyLogging', () => {
|
||||
describe('.logInterception', () => {
|
||||
it('creates a fake log for unmatched requests', () => {
|
||||
const interception = {
|
||||
id: 'request123',
|
||||
request: {
|
||||
url: 'http://foo',
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
},
|
||||
}
|
||||
|
||||
const route = {}
|
||||
|
||||
const ret = Cypress.ProxyLogging.logInterception(interception, route)
|
||||
|
||||
expect(ret.preRequest).to.deep.eq({
|
||||
requestId: 'request123',
|
||||
resourceType: 'other',
|
||||
originalResourceType: 'Request with no browser pre-request',
|
||||
url: 'http://foo',
|
||||
method: 'GET',
|
||||
headers: {},
|
||||
})
|
||||
|
||||
expect(ret.log.get('name')).to.eq('request')
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -1,167 +0,0 @@
|
||||
const { clickCommandLog } = require('../../support/utils')
|
||||
const { _ } = Cypress
|
||||
|
||||
// https://github.com/cypress-io/cypress/pull/5299/files
|
||||
describe('rect highlight', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('/fixtures/dom.html')
|
||||
})
|
||||
|
||||
it('highlight elements are properly positioned', () => {
|
||||
cy.$$('button:first').css({ boxSizing: 'content-box' })
|
||||
|
||||
getAndPin('button:first')
|
||||
|
||||
ensureCorrectHighlightPositions('button:first')
|
||||
})
|
||||
|
||||
it('highlight elements properly positioned for content-box', () => {
|
||||
getAndPin('button.content-box:first')
|
||||
|
||||
ensureCorrectHighlightPositions()
|
||||
})
|
||||
|
||||
it('highlight inline elements', () => {
|
||||
cy.$$('<span>foo</span>').prependTo(cy.$$('body'))
|
||||
|
||||
getAndPin('span:first')
|
||||
|
||||
ensureCorrectHighlightPositions('span:first')
|
||||
})
|
||||
|
||||
it('highlight elements with css transform', () => {
|
||||
cy.$$('button:first').css({ transform: 'scale(1.5) rotate(45deg)' })
|
||||
|
||||
getAndPin('button:first')
|
||||
|
||||
ensureCorrectHighlightPositions('button:first')
|
||||
})
|
||||
|
||||
it('highlight elements with css transform on parent', () => {
|
||||
cy.$$('<div id="parent">parent<div id="child">child</div></div>').css({
|
||||
transform: 'scale(1.5) rotate(45deg) translate(100px, 20px)',
|
||||
height: 40,
|
||||
width: 60,
|
||||
})
|
||||
.prependTo(cy.$$('body'))
|
||||
|
||||
getAndPin('#child')
|
||||
|
||||
// TODO: assert covers element bounding-box
|
||||
ensureCorrectHighlightPositions(null)
|
||||
})
|
||||
|
||||
it('correct target position during click', () => {
|
||||
clickAndPin('#button')
|
||||
ensureCorrectHighlightPositions('#button')
|
||||
ensureCorrectTargetPosition('#button')
|
||||
})
|
||||
|
||||
it('correct target position during click with offset coords', () => {
|
||||
clickAndPin('#button', 5, 10)
|
||||
ensureCorrectHighlightPositions('#button')
|
||||
ensureCorrectTargetPosition('#button')
|
||||
})
|
||||
|
||||
// https://github.com/cypress-io/cypress/issues/7762
|
||||
it('highlights above z-index elements', () => {
|
||||
cy.$$('<div id="absolute-el"></div>').css({
|
||||
position: 'absolute',
|
||||
zIndex: 1000,
|
||||
top: 0,
|
||||
left: 0,
|
||||
height: 50,
|
||||
width: 50,
|
||||
padding: 20,
|
||||
margin: 20,
|
||||
backgroundColor: 'salmon',
|
||||
}).appendTo(cy.$$('body'))
|
||||
|
||||
getAndPin('#absolute-el')
|
||||
ensureCorrectHighlightPositions('#absolute-el')
|
||||
})
|
||||
})
|
||||
|
||||
const ensureCorrectTargetPosition = (sel) => {
|
||||
return cy.wrap(null, { timeout: 400 }).should(() => {
|
||||
const target = cy.$$('div[data-highlight-hitbox]')[0].getBoundingClientRect()
|
||||
|
||||
const dims = {
|
||||
left: target.left + target.width / 2,
|
||||
right: target.left + target.width / 2,
|
||||
top: target.top + target.height / 2,
|
||||
bottom: target.top + target.height / 2,
|
||||
width: 1,
|
||||
height: 1,
|
||||
}
|
||||
|
||||
expectToBeInside(dims, cy.$$(sel)[0].getBoundingClientRect(), 'border-box to match selector bounding-box')
|
||||
})
|
||||
}
|
||||
|
||||
const ensureCorrectHighlightPositions = (sel) => {
|
||||
return cy.wrap(null, { timeout: 400 }).should(() => {
|
||||
const els = {
|
||||
content: cy.$$('div[data-layer=Content]'),
|
||||
padding: cy.$$('div[data-layer=Padding]'),
|
||||
border: cy.$$('div[data-layer=Border]'),
|
||||
}
|
||||
|
||||
const dims = _.mapValues(els, ($el) => {
|
||||
return $el[0].getBoundingClientRect()
|
||||
})
|
||||
|
||||
const doc = els.content[0].ownerDocument
|
||||
|
||||
const contentHighlightCenter = [dims.content.x + dims.content.width / 2, dims.content.y + dims.content.height / 2]
|
||||
|
||||
expect(doc.elementFromPoint(...contentHighlightCenter)).eq(els.content[0])
|
||||
|
||||
expectToBeInside(dims.content, dims.padding, 'content to be inside padding')
|
||||
expectToBeInside(dims.padding, dims.border, 'padding to be inside border')
|
||||
if (sel) {
|
||||
// assert convering bounding-box of element
|
||||
expectToBeEqual(dims.border, cy.$$(sel)[0].getBoundingClientRect(), 'border-box to match selector bounding-box')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getAndPin = (sel) => {
|
||||
cy.get(sel)
|
||||
|
||||
clickCommandLog(sel, 'message-text')
|
||||
}
|
||||
|
||||
const clickAndPin = (sel, ...args) => {
|
||||
cy.get(sel).click(...args)
|
||||
|
||||
clickCommandLog('click')
|
||||
}
|
||||
|
||||
const expectToBeEqual = (rect1, rect2, mes = 'rect to be equal to rect') => {
|
||||
try {
|
||||
expect(rect1.width, 'width').to.be.closeTo(rect2.width, 1)
|
||||
expect(rect1.height, 'height').to.be.closeTo(rect2.height, 1)
|
||||
expect(rect1.top, 'top').to.be.closeTo(rect2.top, 1)
|
||||
expect(rect1.left, 'left').to.be.closeTo(rect2.left, 1)
|
||||
expect(rect1.right, 'right').to.be.closeTo(rect2.right, 1)
|
||||
expect(rect1.bottom, 'bottom').to.be.closeTo(rect2.bottom, 1)
|
||||
} catch (e) {
|
||||
e.message = `\nExpected ${mes}\n${e.message}`
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
const expectToBeInside = (rectInner, rectOuter, mes = 'rect to be inside rect') => {
|
||||
try {
|
||||
expect(rectInner.width, 'width').lte(rectOuter.width)
|
||||
expect(rectInner.height, 'height').lte(rectOuter.height)
|
||||
expect(rectInner.top, 'top').gte(rectOuter.top)
|
||||
expect(rectInner.left, 'left').gte(rectOuter.left)
|
||||
expect(rectInner.right, 'right').lte(rectOuter.right)
|
||||
expect(rectInner.bottom, 'bottom').lte(rectOuter.bottom)
|
||||
} catch (e) {
|
||||
e.message = `\nExpected ${mes}\n${e.message}`
|
||||
throw e
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
describe('selector_playground', () => {
|
||||
it('draws rect over currently hovered element', () => {
|
||||
cy.visit('/fixtures/dom.html')
|
||||
.then(() => {
|
||||
// We trick the selector-playground into rendering while the test is running
|
||||
top.Runner.configureMobx({ enforceActions: 'never' })
|
||||
top.Runner.state.isRunning = false
|
||||
|
||||
const $highlightBtn = cy.$$('button.highlight-toggle:visible', top.document)
|
||||
|
||||
if (!$highlightBtn.length) {
|
||||
const $btn = cy.$$('button.selector-playground-toggle', top.document)
|
||||
|
||||
$btn.click()
|
||||
} else {
|
||||
if (!$highlightBtn.hasClass('active')) {
|
||||
$highlightBtn.click()
|
||||
}
|
||||
}
|
||||
|
||||
cy.get('input:first')
|
||||
.trigger('mousemove', { force: true })
|
||||
.should(expectToBeCovered)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {JQuery<HTMLElement>} $el
|
||||
*/
|
||||
const expectToBeCovered = ($el) => {
|
||||
const el = $el[0]
|
||||
const rect = el.getBoundingClientRect()
|
||||
|
||||
const elAtPoint = el.ownerDocument.elementFromPoint(rect.left, rect.top)
|
||||
|
||||
expect(el).not.eq(elAtPoint)
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
/* eslint-disable @cypress/dev/skip-comment,mocha/no-exclusive-tests */
|
||||
|
||||
describe('per-test config', () => {
|
||||
const testState = {
|
||||
ranFirefox: false,
|
||||
ranChrome: false,
|
||||
ranChromium: false,
|
||||
ranElectron: false,
|
||||
}
|
||||
|
||||
after(function () {
|
||||
if (hasOnly(this.currentTest)) return
|
||||
|
||||
if (Cypress.browser.family === 'firefox') {
|
||||
return expect(testState).deep.eq({
|
||||
ranChrome: false,
|
||||
ranChromium: false,
|
||||
ranFirefox: true,
|
||||
ranElectron: false,
|
||||
})
|
||||
}
|
||||
|
||||
if (Cypress.browser.name === 'chrome') {
|
||||
return expect(testState).deep.eq({
|
||||
ranChrome: true,
|
||||
ranChromium: false,
|
||||
ranFirefox: false,
|
||||
ranElectron: false,
|
||||
})
|
||||
}
|
||||
|
||||
if (Cypress.browser.name === 'chromium') {
|
||||
return expect(testState).deep.eq({
|
||||
ranChrome: false,
|
||||
ranChromium: true,
|
||||
ranFirefox: false,
|
||||
ranElectron: false,
|
||||
})
|
||||
}
|
||||
|
||||
if (Cypress.browser.name === 'electron') {
|
||||
return expect(testState).deep.eq({
|
||||
ranChrome: false,
|
||||
ranChromium: false,
|
||||
ranFirefox: false,
|
||||
ranElectron: true,
|
||||
})
|
||||
}
|
||||
|
||||
throw new Error('should have made assertion')
|
||||
})
|
||||
|
||||
it('set various config values', {
|
||||
defaultCommandTimeout: 200,
|
||||
env: {
|
||||
FOO_VALUE: 'foo',
|
||||
},
|
||||
}, () => {
|
||||
cy.visit('/fixtures/generic.html')
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(200)
|
||||
expect(Cypress.env('FOO_VALUE')).eq('foo')
|
||||
})
|
||||
|
||||
it('does not leak various config values', {
|
||||
}, () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).not.eq(200)
|
||||
expect(Cypress.config('defaultCommandTimeout')).not.eq(200)
|
||||
expect(Cypress.env('FOO_VALUE')).not.eq('foo')
|
||||
})
|
||||
|
||||
it('can set viewport', {
|
||||
viewportWidth: 400,
|
||||
viewportHeight: 200,
|
||||
}, () => {
|
||||
expect(Cypress.config().viewportHeight).eq(200)
|
||||
expect(Cypress.config().viewportWidth).eq(400)
|
||||
})
|
||||
|
||||
it('can specify only run in chrome', {
|
||||
browser: 'chrome',
|
||||
}, () => {
|
||||
testState.ranChrome = true
|
||||
expect(Cypress.browser.name).eq('chrome')
|
||||
})
|
||||
|
||||
it('can specify only run in chromium', {
|
||||
browser: 'chromium',
|
||||
}, () => {
|
||||
testState.ranChromium = true
|
||||
expect(Cypress.browser.family).eq('chromium')
|
||||
})
|
||||
|
||||
it('can specify only run in firefox', {
|
||||
browser: 'firefox',
|
||||
}, () => {
|
||||
testState.ranFirefox = true
|
||||
expect(Cypress.browser.name).eq('firefox')
|
||||
})
|
||||
|
||||
it('can specify only run in electron', {
|
||||
browser: 'electron',
|
||||
}, () => {
|
||||
testState.ranElectron = true
|
||||
expect(Cypress.browser.name).eq('electron')
|
||||
})
|
||||
|
||||
describe('mutating global config via Cypress.config and Cypress.env', () => {
|
||||
it('1/2 global config and env', {
|
||||
defaultCommandTimeout: 1234,
|
||||
env: {
|
||||
FOO: '0',
|
||||
},
|
||||
}, () => {
|
||||
Cypress.config('responseTimeout', 1111)
|
||||
expect(Cypress.config('responseTimeout')).eq(1111)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(1234)
|
||||
|
||||
Cypress.env('BAR', '1')
|
||||
expect(Cypress.env('FOO')).eq('0')
|
||||
expect(Cypress.env('BAR')).eq('1')
|
||||
})
|
||||
|
||||
it('2/2 global config and env', () => {
|
||||
expect(Cypress.config('responseTimeout')).eq(1111)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(4000)
|
||||
|
||||
expect(Cypress.env('FOO')).eq(undefined)
|
||||
expect(Cypress.env('BAR')).eq('1')
|
||||
})
|
||||
})
|
||||
|
||||
describe('in beforeEach', () => {
|
||||
it('set various config values', {
|
||||
defaultCommandTimeout: 200,
|
||||
env: {
|
||||
FOO_VALUE: 'foo',
|
||||
},
|
||||
}, () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(200)
|
||||
expect(Cypress.env('FOO_VALUE')).eq('foo')
|
||||
})
|
||||
|
||||
beforeEach(() => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(200)
|
||||
expect(Cypress.env('FOO_VALUE')).eq('foo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('in afterEach', () => {
|
||||
it('set various config values', {
|
||||
defaultCommandTimeout: 200,
|
||||
env: {
|
||||
FOO_VALUE: 'foo',
|
||||
},
|
||||
}, () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(200)
|
||||
expect(Cypress.env('FOO_VALUE')).eq('foo')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
expect(Cypress.config('defaultCommandTimeout')).eq(200)
|
||||
expect(Cypress.env('FOO_VALUE')).eq('foo')
|
||||
})
|
||||
})
|
||||
|
||||
describe('in suite', () => {
|
||||
describe('config in suite', {
|
||||
defaultCommandTimeout: 200,
|
||||
}, () => {
|
||||
it('test', () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
|
||||
it('test', () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
|
||||
it('test', () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('in suite (context)', () => {
|
||||
context('config in suite', {
|
||||
defaultCommandTimeout: 200,
|
||||
}, () => {
|
||||
it('test', () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
|
||||
it('test', () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
|
||||
it('test', () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('in nested suite', () => {
|
||||
describe('config in suite', {
|
||||
foo: true,
|
||||
defaultCommandTimeout: 200,
|
||||
}, () => {
|
||||
it('has config.foo', () => {
|
||||
expect(Cypress.config().foo).ok
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
|
||||
describe('inner suite', {
|
||||
bar: true,
|
||||
}, () => {
|
||||
it('has config.bar', () => {
|
||||
expect(Cypress.config().bar).ok
|
||||
})
|
||||
|
||||
it('has config.bar and config.foo', () => {
|
||||
expect(Cypress.config().bar).ok
|
||||
expect(Cypress.config().foo).ok
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(200)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('in double nested suite', () => {
|
||||
describe('config in suite', {
|
||||
foo: true,
|
||||
}, () => {
|
||||
describe('inner suite', { bar: true }, () => {
|
||||
it('has config.bar', () => {
|
||||
expect(Cypress.config().bar).ok
|
||||
expect(Cypress.config().foo).ok
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('in mulitple nested suites', {
|
||||
foo: false,
|
||||
}, () => {
|
||||
describe('config in suite', {
|
||||
foo: true,
|
||||
}, () => {
|
||||
describe('inner suite 1', { bar: true }, () => {
|
||||
it('has config.bar', () => {
|
||||
expect(Cypress.config().bar).ok
|
||||
expect(Cypress.config().foo).ok
|
||||
})
|
||||
})
|
||||
|
||||
describe('inner suite 2', { baz: true }, () => {
|
||||
it('has config.baz', () => {
|
||||
expect(Cypress.config().bar).not.ok
|
||||
expect(Cypress.config().baz).ok
|
||||
expect(Cypress.config().foo).ok
|
||||
})
|
||||
})
|
||||
|
||||
describe('inner suite 3', () => {
|
||||
it('has only config.foo', () => {
|
||||
expect(Cypress.config().bar).not.ok
|
||||
expect(Cypress.config().baz).not.ok
|
||||
expect(Cypress.config().foo).ok
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('in multiple nested suites', () => {
|
||||
describe('config in suite', {
|
||||
foo: true,
|
||||
}, () => {
|
||||
describe('inner suite 1', { bar: true }, () => {
|
||||
it('has config.bar', () => {
|
||||
expect(Cypress.config().bar).ok
|
||||
expect(Cypress.config().foo).ok
|
||||
})
|
||||
})
|
||||
|
||||
describe('inner suite 2', { baz: true }, () => {
|
||||
it('has config.bar', () => {
|
||||
expect(Cypress.config().bar).not.ok
|
||||
expect(Cypress.config().baz).ok
|
||||
expect(Cypress.config().foo).ok
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('empty config', {}, () => {
|
||||
it('empty config in test', {}, () => {
|
||||
expect(true).ok
|
||||
})
|
||||
})
|
||||
|
||||
specify('works with it & specify', { defaultCommandTimeout: 100 }, () => {
|
||||
expect(Cypress.config().defaultCommandTimeout).eq(100)
|
||||
})
|
||||
|
||||
describe('config changes after run', () => {
|
||||
let defaultCommandTimeout
|
||||
|
||||
it('1/2', {
|
||||
defaultCommandTimeout: 1234,
|
||||
}, () => {
|
||||
cy.on('test:after:run', () => {
|
||||
defaultCommandTimeout = Cypress.config('defaultCommandTimeout')
|
||||
})
|
||||
})
|
||||
|
||||
it('2/2', () => {
|
||||
expect(defaultCommandTimeout).eq(1234)
|
||||
})
|
||||
})
|
||||
|
||||
describe('xit, xdescribe', () => {
|
||||
xit('should be skipped', {}, () => {})
|
||||
xspecify('should be skipped', {}, () => {})
|
||||
xdescribe('suite should be skipped', {}, () => {
|
||||
it('skipped')
|
||||
})
|
||||
|
||||
xcontext('suite should be skipped', {}, () => {
|
||||
it('skipped')
|
||||
})
|
||||
|
||||
describe('non-skipped test', () => {
|
||||
it('foo', () => {})
|
||||
})
|
||||
|
||||
after(function () {
|
||||
expect(this.currentTest?.parent?.parent?.tests).length(2)
|
||||
expect(this.currentTest?.parent?.parent?.tests[0]).property('state', 'pending')
|
||||
expect(this.currentTest?.parent?.parent?.tests[1]).property('state', 'pending')
|
||||
expect(this.currentTest?.parent?.parent?.suites[0].tests[0]).property('state', 'pending')
|
||||
expect(this.currentTest?.parent?.parent?.suites[1].tests[0]).property('state', 'pending')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('viewport', () => {
|
||||
// https://github.com/cypress-io/cypress/issues/7631
|
||||
it('can set viewport in testConfigOverrides', { viewportWidth: 200, viewportHeight: 100 }, () => {
|
||||
cy.visit('/fixtures/generic.html')
|
||||
cy.window().then((win) => {
|
||||
expect(win.innerWidth).eq(200)
|
||||
expect(win.innerHeight).eq(100)
|
||||
})
|
||||
})
|
||||
|
||||
it('viewport does not leak between tests', () => {
|
||||
cy.visit('/fixtures/generic.html')
|
||||
cy.window().then((win) => {
|
||||
expect(win.innerWidth).eq(1000)
|
||||
expect(win.innerHeight).eq(660)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('testConfigOverrides baseUrl @slow', () => {
|
||||
it('visit 1', { baseUrl: 'http://localhost:3501' }, () => {
|
||||
cy.visit('/fixtures/generic.html')
|
||||
cy.url().should('eq', 'http://localhost:3501/fixtures/generic.html')
|
||||
})
|
||||
|
||||
it('visit 2', { baseUrl: 'http://localhost:3500' }, () => {
|
||||
cy.visit('/fixtures/generic.html')
|
||||
cy.url().should('eq', 'http://localhost:3500/fixtures/generic.html')
|
||||
})
|
||||
})
|
||||
|
||||
describe('cannot set read-only properties', () => {
|
||||
afterEach(() => {
|
||||
window.top.__cySkipValidateConfig = true
|
||||
})
|
||||
|
||||
it('throws if mutating read-only config with Cypress.config()', (done) => {
|
||||
window.top.__cySkipValidateConfig = false
|
||||
cy.on('fail', (err) => {
|
||||
expect(err.message).to.include('`Cypress.config()` cannot mutate option `chromeWebSecurity` because it is a read-only property.')
|
||||
done()
|
||||
})
|
||||
|
||||
Cypress.config('chromeWebSecurity', false)
|
||||
})
|
||||
|
||||
it('does not throw for non-Cypress config values', () => {
|
||||
expect(() => {
|
||||
Cypress.config('foo', 'bar')
|
||||
}).to.not.throw()
|
||||
})
|
||||
})
|
||||
|
||||
function hasOnly (test) {
|
||||
let curSuite = test.parent
|
||||
let hasOnly = false
|
||||
|
||||
while (curSuite) {
|
||||
if (curSuite._onlySuites.length || curSuite._onlyTests.length) {
|
||||
hasOnly = true
|
||||
}
|
||||
|
||||
curSuite = curSuite.parent
|
||||
}
|
||||
|
||||
return hasOnly
|
||||
}
|
||||
Reference in New Issue
Block a user