Skip to content

Commit

Permalink
Merge branch 'develop' into typescript-server
Browse files Browse the repository at this point in the history
* develop:
  Update error message when record key not found for project (#3628)
  Removing light (300) font weight from spec links in desktop GUI (#3065)
  chore(deps): update dtslint to 0.5.1 馃専 (#3611)
  separate dtslint into its own CircleCI job (#3528)
  chore(deps): update dependency enzyme-adapter-react-16 to version 1.10.0 馃専 (#3601)
  Visit with a POST and/or custom headers (#3489)
  try v8 for reporter and runner caches (#3600)
  match the reporter cache key (#3598)
  increment reporter cache key (#3596)
  Pass all extra parameters to setInterval/setTimeout callback functions (#3593)
  • Loading branch information
tgriesser committed Mar 4, 2019
2 parents 1f9c5af + 0a87734 commit c36f6cc
Show file tree
Hide file tree
Showing 16 changed files with 206 additions and 37 deletions.
21 changes: 17 additions & 4 deletions circle.yml
Expand Up @@ -85,9 +85,9 @@ jobs:
- restore_cache:
key: v5-{{ arch }}-{{ .Branch }}-deps-launcher
- restore_cache:
key: v5-{{ arch }}-{{ .Branch }}-deps-reporter
key: v8-{{ arch }}-{{ .Branch }}-deps-reporter
- restore_cache:
key: v5-{{ arch }}-{{ .Branch }}-deps-runner
key: v8-{{ arch }}-{{ .Branch }}-deps-runner
- restore_cache:
key: v6-{{ arch }}-{{ .Branch }}-deps-server
- restore_cache:
Expand Down Expand Up @@ -159,11 +159,11 @@ jobs:
paths:
- packages/launcher/node_modules
- save_cache:
key: v5-{{ arch }}-{{ .Branch }}-deps-reporter-{{ checksum "packages/reporter/package.json" }}
key: v8-{{ arch }}-{{ .Branch }}-deps-reporter-{{ checksum "packages/reporter/package.json" }}
paths:
- packages/reporter/node_modules
- save_cache:
key: v5-{{ arch }}-{{ .Branch }}-deps-runner-{{ checksum "packages/runner/package.json" }}
key: v8-{{ arch }}-{{ .Branch }}-deps-runner-{{ checksum "packages/runner/package.json" }}
paths:
- packages/runner/node_modules
- save_cache:
Expand Down Expand Up @@ -228,6 +228,16 @@ jobs:
- store_test_results:
path: /tmp/cypress

lint-typescript:
<<: *defaults
parallelism: 1
steps:
- attach_workspace:
at: ~/
- run:
command: npm run dtslint
working_directory: cli

"server-unit-tests":
<<: *defaults
parallelism: 2
Expand Down Expand Up @@ -677,6 +687,9 @@ linux-workflow: &linux-workflow
name: Linux lint
requires:
- build
- lint-typescript:
requires:
- build
# unit, integration and e2e tests
- unit-tests:
requires:
Expand Down
4 changes: 2 additions & 2 deletions cli/package.json
Expand Up @@ -13,7 +13,7 @@
"pretest": "npm run check-deps-pre",
"test": "npm run test-unit",
"pretest-unit": "npm run check-deps-pre",
"test-unit": "npm run dtslint && npm run unit",
"test-unit": "npm run unit",
"pretest-watch": "npm run check-deps-pre",
"test-watch": "npm run unit -- --watch",
"check-deps": "node ../scripts/check-deps.js --verbose",
Expand Down Expand Up @@ -88,7 +88,7 @@
"chai-string": "1.4.0",
"clear-module": "2.1.0",
"dependency-check": "2.10.1",
"dtslint": "0.5.0",
"dtslint": "0.5.1",
"execa-wrap": "1.4.0",
"mock-fs": "4.8.0",
"nock": "9.6.1",
Expand Down
5 changes: 5 additions & 0 deletions cli/types/index.d.ts
Expand Up @@ -1588,9 +1588,14 @@ declare namespace Cypress {
* @example
* cy.visit('http://localhost:3000')
* cy.visit('/somewhere') // opens ${baseUrl}/somewhere
* cy.visit({
* url: 'http://google.com',
* method: 'POST'
* })
*
*/
visit(url: string, options?: Partial<VisitOptions>): Chainable<Window>
visit(options: Partial<VisitOptions> & { url: string }): Chainable<Window>

/**
* Wait for a number of milliseconds.
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-gui/src/specs/specs.scss
Expand Up @@ -144,7 +144,7 @@
}

.file > a {
font-weight: 300;
font-weight: 400;
border-bottom: 1px dotted #eeeeee;
padding: 4px 0;
font-family: $font-sans;
Expand Down
40 changes: 35 additions & 5 deletions packages/driver/src/cy/commands/navigation.coffee
Expand Up @@ -28,6 +28,11 @@ reset = (test = {}) ->

id = test.id

VALID_VISIT_METHODS = ['GET', 'POST']

isValidVisitMethod = (method) ->
_.includes(VALID_VISIT_METHODS, method)

timedOutWaitingForPageLoad = (ms, log) ->
$utils.throwErrByPath("navigation.timed_out", {
onFail: log
Expand Down Expand Up @@ -260,7 +265,7 @@ module.exports = (Commands, Cypress, cy, state, config) ->
Cypress.backend(
"resolve:url",
url,
_.pick(options, "failOnStatusCode", "auth")
_.pick(options, "auth", "failOnStatusCode", "method", "body", "headers")
)
.then (resp = {}) ->
switch
Expand Down Expand Up @@ -456,22 +461,45 @@ module.exports = (Commands, Cypress, cy, state, config) ->
$utils.throwErrByPath("go.invalid_argument", { onFail: options._log })

visit: (url, options = {}) ->
if options.url and url
$utils.throwErrByPath("visit.no_duplicate_url", { args: { optionsUrl: options.url, url: url }})

if _.isObject(url) and _.isEqual(options, {})
## options specified as only argument
options = url
url = options.url

if not _.isString(url)
$utils.throwErrByPath("visit.invalid_1st_arg")

_.defaults(options, {
auth: null
failOnStatusCode: true
method: 'GET'
body: null
headers: {}
log: true
timeout: config("pageLoadTimeout")
onBeforeLoad: ->
onLoad: ->
})

if not isValidVisitMethod(options.method)
$utils.throwErrByPath("visit.invalid_method", { args: { method: options.method }})

if not _.isObject(options.headers)
$utils.throwErrByPath("visit.invalid_headers")

consoleProps = {}

if options.log
message = url

if options.method != 'GET'
message = "#{options.method} #{message}"

options._log = Cypress.log({
message: message
consoleProps: -> consoleProps
})

Expand Down Expand Up @@ -598,11 +626,13 @@ module.exports = (Commands, Cypress, cy, state, config) ->
if url isnt originalUrl
consoleProps["Original Url"] = originalUrl

if options.log and redirects and redirects.length
indicateRedirects = ->
[originalUrl].concat(redirects).join(" -> ")
if options.log
message = options._log.get('message')

if redirects and redirects.length
message = [message].concat(redirects).join(" -> ")

options._log.set({message: indicateRedirects()})
options._log.set({message: message})

consoleProps["Resolved Url"] = url
consoleProps["Redirects"] = redirects
Expand Down
8 changes: 1 addition & 7 deletions packages/driver/src/cy/timers.js
Expand Up @@ -82,13 +82,7 @@ const create = () => {
let timerId
let [fnOrCode, delay, ...params] = args

const timerOverride = (timestamp) => {
// https://github.com/cypress-io/cypress/issues/2725
// requestAnimationFrame yields a high res timestamp
if (arguments.length) {
params = [timestamp]
}

const timerOverride = (...params) => {
// if we're currently paused then we need
// to enqueue this timer callback and invoke
// it immediately once we're unpaused
Expand Down
10 changes: 9 additions & 1 deletion packages/driver/src/cypress/error_messages.coffee
Expand Up @@ -845,7 +845,15 @@ module.exports = {
missing_preset: "#{cmd('viewport')} could not find a preset for: '{{preset}}'. Available presets are: {{presets}}"

visit:
invalid_1st_arg: "#{cmd('visit')} must be called with a string as its 1st argument"
invalid_1st_arg: "#{cmd('visit')} must be called with a URL or an options object containing a URL as its 1st argument"
invalid_method: "#{cmd('visit')} was called with an invalid method: '{{method}}'. Method can only be GET or POST."
invalid_headers: "#{cmd('visit')} requires the 'headers' option to be an object."
no_duplicate_url: """
#{cmd('visit')} must be called with only one URL. You specified two URLs:
URL from the `options` object: {{optionsUrl}}
URL from the `url` parameter: {{url}}
"""
cannot_visit_2nd_domain: """
#{cmd('visit')} failed because you are attempting to visit a second unique domain.
Expand Down
Expand Up @@ -580,6 +580,37 @@ describe "src/cy/commands/navigation", ->
expect(win.bar).to.not.exist
expect(onLoad).not.to.have.been.called

it "can send headers", ->
cy.visit({
url: "http://localhost:3500/dump-headers",
headers: {
"x-foo-baz": "bar-quux"
}
})
cy.contains('"x-foo-baz":"bar-quux"')

describe "can send a POST request", ->
it "automatically urlencoded using an object body", ->
cy.visit("http://localhost:3500/post-only", {
method: "POST",
body: {
bar: "baz"
}
})
cy.contains("it worked!").contains("{\"bar\":\"baz\"}")

it "with any string body and headers", ->
cy.visit("http://localhost:3500/post-only", {
method: "POST",
headers: {
"content-type": "application/json"
}
body: JSON.stringify({
bar: "baz"
})
})
cy.contains("it worked!").contains("{\"bar\":\"baz\"}")

describe "when origins don't match", ->
beforeEach ->
Cypress.emit("test:before:run", { id: 888 })
Expand Down Expand Up @@ -856,6 +887,16 @@ describe "src/cy/commands/navigation", ->
"http://localhost:3500/foo -> 1 -> 2"
)

it "indicates POST in the message", ->
cy.visit("http://localhost:3500/post-only", {
method: "POST"
}).then ->
lastLog = @lastLog

expect(lastLog.get("message")).to.eq(
"POST http://localhost:3500/post-only"
)

it "displays note in consoleProps when visiting the same page with a hash", ->
cy.visit("http://localhost:3500/fixtures/generic.html#foo")
.visit("http://localhost:3500/fixtures/generic.html#foo")
Expand Down Expand Up @@ -934,11 +975,40 @@ describe "src/cy/commands/navigation", ->

it "throws when url isnt a string", (done) ->
cy.on "fail", (err) ->
expect(err.message).to.eq "cy.visit() must be called with a string as its 1st argument"
expect(err.message).to.eq "cy.visit() must be called with a URL or an options object containing a URL as its 1st argument"
done()

cy.visit()

it "throws when url is specified twice", (done) ->
cy.on "fail", (err) ->
expect(err.message).to.contain "cy.visit() must be called with only one URL. You specified two URLs"
done()

cy.visit("http://foobarbaz", {
url: "http://foobarbaz"
})

it "throws when method is unsupported", (done) ->
cy.on "fail", (err) ->
expect(err.message).to.contain "cy.visit() was called with an invalid method: 'FOO'"
done()

cy.visit({
url: "http://foobarbaz",
method: "FOO"
})

it "throws when headers is not an object", (done) ->
cy.on "fail", (err) ->
expect(err.message).to.contain "cy.visit() requires the 'headers' option to be an object"
done()

cy.visit({
url: "http://foobarbaz",
headers: "quux"
})

it "throws when attempting to visit a 2nd domain on different port", (done) ->
cy.on "fail", (err) =>
lastLog = @lastLog
Expand Down Expand Up @@ -1259,7 +1329,7 @@ describe "src/cy/commands/navigation", ->

## https://github.com/cypress-io/cypress/issues/3101
[{
contentType: 'application/json',
contentType: 'application/json',
pathName: 'json-content-type'
}, {
contentType: 'text/html; charset=utf-8,text/html',
Expand Down
37 changes: 37 additions & 0 deletions packages/driver/test/cypress/integration/cy/timers_spec.js
Expand Up @@ -37,6 +37,23 @@ describe('driver/src/cy/timers', () => {
})
})

it('setTimeout can pass multiple parameters to the target function', () => {
cy
.log('setTimeout should call target with two parameters')
.window()
.then((win) => {
win.foo = null
win.setFoo = (bar, baz) => {
win.foo = bar + baz
}

win.setTimeout(win.setFoo, 0, 'bar', 'baz')

cy
.window().its('foo').should('eq', 'barbaz')
})
})

it('setInterval is called through', () => {
cy
.log('setInterval should be called')
Expand Down Expand Up @@ -73,6 +90,26 @@ describe('driver/src/cy/timers', () => {
})
})

it('setInterval can pass multiple parameters to the target function', () => {
cy
.log('setInterval should call target with two parameters')
.window()
.then((win) => {
win.foo = null
win.setFoo = (bar, baz) => {
win.foo = bar + baz
}

const id1 = win.setInterval(win.setFoo, 1, 'bar', 'baz')

cy
.window().its('foo').should('eq', 'barbaz')
.then(() => {
win.clearInterval(id1)
})
})
})

it('requestAnimationFrame is called through', () => {
cy
.log('requestAnimationFrame should be called')
Expand Down
6 changes: 6 additions & 0 deletions packages/driver/test/support/server.coffee
Expand Up @@ -72,6 +72,12 @@ niv.install("react-dom@15.6.1")
res.setHeader('Content-Type', 'text/html; charset=utf-8,text/html')
res.end("<html><head><title>Test</title></head><body><center>Hello</center></body></html>")

app.post '/post-only', (req, res) ->
res.send("<html><body>it worked!<br>request body:<br>#{JSON.stringify(req.body)}</body></html>")

app.get '/dump-headers', (req, res) ->
res.send("<html><body>request headers:<br>#{JSON.stringify(req.headers)}</body></html>")

app.get "/status-404", (req, res) ->
res
.status(404)
Expand Down
2 changes: 1 addition & 1 deletion packages/reporter/package.json
Expand Up @@ -33,7 +33,7 @@
"classnames": "2.2.6",
"css-element-queries": "0.4.0",
"enzyme": "3.9.0",
"enzyme-adapter-react-16": "1.9.1",
"enzyme-adapter-react-16": "1.10.0",
"font-awesome": "4.7.0",
"jsdom": "13.2.0",
"lodash": "4.17.11",
Expand Down
2 changes: 1 addition & 1 deletion packages/runner/package.json
Expand Up @@ -32,7 +32,7 @@
"chai-enzyme": "1.0.0-beta.1",
"classnames": "2.2.6",
"enzyme": "3.9.0",
"enzyme-adapter-react-16": "1.9.1",
"enzyme-adapter-react-16": "1.10.0",
"font-awesome": "4.7.0",
"jsdom": "13.2.0",
"lodash": "4.17.11",
Expand Down

0 comments on commit c36f6cc

Please sign in to comment.