Files
cypress/packages/server/lib/api.coffee
Brian Mann dc37dff548 server: (WIP) properly pass in browserName + version to API when creating instances (#1000)
* server: (WIP) properly pass in browserName + version to API when creating instances

* server: fixes #854 and failing tests

* server: fix using wrong property on found browser
2017-12-04 00:43:44 -05:00

322 lines
7.1 KiB
CoffeeScript

_ = require("lodash")
os = require("os")
nmi = require("node-machine-id")
request = require("request-promise")
errors = require("request-promise/errors")
Promise = require("bluebird")
pkg = require("@packages/root")
browsers = require('./browsers')
Routes = require("./util/routes")
system = require("./util/system")
debug = require("debug")("cypress:server:api")
rp = request.defaults (params = {}, callback) ->
headers = params.headers ?= {}
_.defaults(headers, {
"x-platform": os.platform()
"x-cypress-version": pkg.version
})
method = params.method.toLowerCase()
request[method](params, callback)
formatResponseBody = (err) ->
## if the body is JSON object
if _.isObject(err.error)
## transform the error message to include the
## stringified body (represented as the 'error' property)
body = JSON.stringify(err.error, null, 2)
err.message = [err.statusCode, body].join("\n\n")
throw err
tagError = (err) ->
err.isApiError = true
throw err
machineId = ->
nmi.machineId()
.catch ->
return null
module.exports = {
ping: ->
rp.get(Routes.ping())
.catch(tagError)
getOrgs: (authToken) ->
rp.get({
url: Routes.orgs()
json: true
auth: {
bearer: authToken
}
})
.catch(tagError)
getProjects: (authToken) ->
rp.get({
url: Routes.projects()
json: true
auth: {
bearer: authToken
}
})
.catch(tagError)
getProject: (projectId, authToken) ->
rp.get({
url: Routes.project(projectId)
json: true
auth: {
bearer: authToken
}
headers: {
"x-route-version": "2"
}
})
.catch(tagError)
getProjectRuns: (projectId, authToken, options = {}) ->
options.page ?= 1
rp.get({
url: Routes.projectRuns(projectId)
json: true
timeout: options.timeout ? 10000
auth: {
bearer: authToken
}
})
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
createRun: (options = {}) ->
debugReturnedBuild = (info) ->
debug("received API response with buildId %s", info.buildId)
debug("and list of specs to run", info.specs)
body = _.pick(options, [
"projectId"
"recordKey"
"commitSha"
"commitBranch"
"commitAuthorName"
"commitAuthorEmail"
"commitMessage"
"remoteOrigin"
"ciParams"
"ciProvider"
"ciBuildNumber",
"groupId",
"specs",
"specPattern"
])
debug("creating project run")
debug("project '%s' group id '%s'", body.projectId, body.groupId)
rp.post({
url: Routes.runs()
json: true
timeout: options.timeout ? 10000
headers: {
"x-route-version": "2"
}
body: body
})
.promise()
.tap(debugReturnedBuild)
.get("buildId")
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
createInstance: (options = {}) ->
{ buildId, spec, timeout } = options
browsers.getByName(options.browser)
.then (browser = {}) ->
## get the formatted browserName
## and version of the browser we're
## about to be running on
{ displayName, version } = browser
system.info()
.then (systemInfo) ->
systemInfo.spec = spec
systemInfo.browserName = displayName
systemInfo.browserVersion = version
rp.post({
url: Routes.instances(buildId)
json: true
timeout: timeout ? 10000
headers: {
"x-route-version": "3"
}
body: systemInfo
})
.promise()
.get("instanceId")
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
updateInstanceStdout: (options = {}) ->
rp.put({
url: Routes.instanceStdout(options.instanceId)
json: true
timeout: options.timeout ? 10000
body: {
stdout: options.stdout
}
})
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
updateInstance: (options = {}) ->
rp.put({
url: Routes.instance(options.instanceId)
json: true
timeout: options.timeout ? 10000
body: _.pick(options, [
"tests"
"duration"
"passes"
"failures"
"pending"
"error"
"video"
"screenshots"
"failingTests"
"ciProvider" ## TODO: don't send this (no reason to)
"cypressConfig"
"stdout"
])
})
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
createRaygunException: (body, authToken, timeout = 3000) ->
rp.post({
url: Routes.exceptions()
json: true
body: body
auth: {
bearer: authToken
}
})
.promise()
.timeout(timeout)
.catch(tagError)
createSignin: (code) ->
machineId()
.then (id) ->
h = {
"x-route-version": "3"
"x-accept-terms": "true"
}
if id
h["x-machine-id"] = id
rp.post({
url: Routes.signin({code: code})
json: true
headers: h
})
.catch errors.StatusCodeError, (err) ->
## reset message to error which is a pure body
## representation of what was sent back from
## the API
err.message = err.error
throw err
.catch(tagError)
createSignout: (authToken) ->
rp.post({
url: Routes.signout()
json: true
auth: {
bearer: authToken
}
})
.catch({statusCode: 401}, ->) ## do nothing on 401
.catch(tagError)
createProject: (projectDetails, remoteOrigin, authToken) ->
rp.post({
url: Routes.projects()
json: true
auth: {
bearer: authToken
}
headers: {
"x-route-version": "2"
}
body: {
name: projectDetails.projectName
orgId: projectDetails.orgId
public: projectDetails.public
remoteOrigin: remoteOrigin
}
})
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
getProjectRecordKeys: (projectId, authToken) ->
rp.get({
url: Routes.projectRecordKeys(projectId)
json: true
auth: {
bearer: authToken
}
})
.catch(tagError)
requestAccess: (projectId, authToken) ->
rp.post({
url: Routes.membershipRequests(projectId)
json: true
auth: {
bearer: authToken
}
})
.catch(errors.StatusCodeError, formatResponseBody)
.catch(tagError)
getLoginUrl: ->
rp.get({
url: Routes.auth(),
json: true
})
.promise()
.get("url")
.catch(tagError)
_projectToken: (method, projectId, authToken) ->
rp({
method: method
url: Routes.projectToken(projectId)
json: true
auth: {
bearer: authToken
}
headers: {
"x-route-version": "2"
}
})
.promise()
.get("apiToken")
.catch(tagError)
getProjectToken: (projectId, authToken) ->
@_projectToken("get", projectId, authToken)
updateProjectToken: (projectId, authToken) ->
@_projectToken("put", projectId, authToken)
}