Best JavaScript code snippet using cypress
project_spec.js
Source:project_spec.js
1require('../spec_helper')2const mockedEnv = require('mocked-env')3const path = require('path')4const commitInfo = require('@cypress/commit-info')5const Fixtures = require('../support/helpers/fixtures')6const api = require(`${root}lib/api`)7const user = require(`${root}lib/user`)8const cache = require(`${root}lib/cache`)9const config = require(`${root}lib/config`)10const scaffold = require(`${root}lib/scaffold`)11const { ServerE2E } = require(`${root}lib/server-e2e`)12const { ProjectE2E } = require(`${root}lib/project-e2e`)13const Automation = require(`${root}lib/automation`)14const savedState = require(`${root}lib/saved_state`)15const preprocessor = require(`${root}lib/plugins/preprocessor`)16const plugins = require(`${root}lib/plugins`)17const { fs } = require(`${root}lib/util/fs`)18const settings = require(`${root}lib/util/settings`)19const Watchers = require(`${root}lib/watchers`)20const { SocketE2E } = require(`${root}lib/socket-e2e`)21xdescribe('lib/project-e2e', () => {22 beforeEach(function () {23 Fixtures.scaffold()24 this.todosPath = Fixtures.projectPath('todos')25 this.idsPath = Fixtures.projectPath('ids')26 this.pristinePath = Fixtures.projectPath('pristine')27 return settings.read(this.todosPath).then((obj = {}) => {28 ({ projectId: this.projectId } = obj)29 return config.set({ projectName: 'project', projectRoot: '/foo/bar' })30 .then((config1) => {31 this.config = config132 this.project = new ProjectE2E(this.todosPath)33 })34 })35 })36 afterEach(function () {37 Fixtures.remove()38 if (this.project) {39 this.project.close()40 }41 })42 it('requires a projectRoot', () => {43 const fn = () => new ProjectE2E()44 expect(fn).to.throw('Instantiating lib/project requires a projectRoot!')45 })46 it('always resolves the projectRoot to be absolute', () => {47 const p = new ProjectE2E('../foo/bar')48 expect(p.projectRoot).not.to.eq('../foo/bar')49 expect(p.projectRoot).to.eq(path.resolve('../foo/bar'))50 })51 context('#saveState', () => {52 beforeEach(function () {53 const integrationFolder = 'the/save/state/test'54 sinon.stub(config, 'get').withArgs(this.todosPath).resolves({ integrationFolder })55 sinon.stub(this.project, 'determineIsNewProject').withArgs(integrationFolder).resolves(false)56 this.project.cfg = { integrationFolder }57 return savedState.create(this.project.projectRoot)58 .then((state) => state.remove())59 })60 afterEach(function () {61 return savedState.create(this.project.projectRoot)62 .then((state) => state.remove())63 })64 it('saves state without modification', function () {65 return this.project.saveState()66 .then((state) => expect(state).to.deep.eq({}))67 })68 it('adds property', function () {69 return this.project.saveState()70 .then(() => this.project.saveState({ foo: 42 }))71 .then((state) => expect(state).to.deep.eq({ foo: 42 }))72 })73 it('adds second property', function () {74 return this.project.saveState()75 .then(() => this.project.saveState({ foo: 42 }))76 .then(() => this.project.saveState({ bar: true }))77 .then((state) => expect(state).to.deep.eq({ foo: 42, bar: true }))78 })79 it('modifes property', function () {80 return this.project.saveState()81 .then(() => this.project.saveState({ foo: 42 }))82 .then(() => this.project.saveState({ foo: 'modified' }))83 .then((state) => expect(state).to.deep.eq({ foo: 'modified' }))84 })85 })86 context('#getConfig', () => {87 const integrationFolder = 'foo/bar/baz'88 beforeEach(function () {89 sinon.stub(config, 'get').withArgs(this.todosPath, { foo: 'bar' }).resolves({ baz: 'quux', integrationFolder })90 sinon.stub(this.project, 'determineIsNewProject').withArgs(integrationFolder).resolves(false)91 })92 it('calls config.get with projectRoot + options + saved state', function () {93 return savedState.create(this.todosPath)94 .then((state) => {95 sinon.stub(state, 'get').resolves({ reporterWidth: 225 })96 this.project.getConfig({ foo: 'bar' })97 .then((cfg) => {98 expect(cfg).to.deep.eq({99 integrationFolder,100 isNewProject: false,101 baz: 'quux',102 state: {103 reporterWidth: 225,104 },105 })106 })107 })108 })109 it('resolves if cfg is already set', function () {110 this.project.cfg = {111 integrationFolder,112 foo: 'bar',113 }114 return this.project.getConfig()115 .then((cfg) => {116 expect(cfg).to.deep.eq({117 integrationFolder,118 foo: 'bar',119 })120 })121 })122 it('sets cfg.isNewProject to false when state.showedOnBoardingModal is true', function () {123 return savedState.create(this.todosPath)124 .then((state) => {125 sinon.stub(state, 'get').resolves({ showedOnBoardingModal: true })126 this.project.getConfig({ foo: 'bar' })127 .then((cfg) => {128 expect(cfg).to.deep.eq({129 integrationFolder,130 isNewProject: false,131 baz: 'quux',132 state: {133 showedOnBoardingModal: true,134 },135 })136 })137 })138 })139 it('does not set cfg.isNewProject when cfg.isTextTerminal', function () {140 const cfg = { isTextTerminal: true }141 config.get.resolves(cfg)142 sinon.stub(this.project, '_setSavedState').resolves(cfg)143 return this.project.getConfig({ foo: 'bar' })144 .then((cfg) => {145 expect(cfg).not.to.have.property('isNewProject')146 })147 })148 })149 context('#open', () => {150 beforeEach(function () {151 sinon.stub(this.project, 'watchSettingsAndStartWebsockets').resolves()152 sinon.stub(this.project, 'checkSupportFile').resolves()153 sinon.stub(this.project, 'scaffold').resolves()154 sinon.stub(this.project, 'getConfig').resolves(this.config)155 sinon.stub(ServerE2E.prototype, 'open').resolves([])156 sinon.stub(ServerE2E.prototype, 'reset')157 sinon.stub(config, 'updateWithPluginValues').returns(this.config)158 sinon.stub(scaffold, 'plugins').resolves()159 sinon.stub(plugins, 'init').resolves()160 })161 it('calls #watchSettingsAndStartWebsockets with options + config', function () {162 const opts = { changeEvents: false, onAutomationRequest () {} }163 this.project.cfg = {}164 return this.project.open(opts).then(() => {165 expect(this.project.watchSettingsAndStartWebsockets).to.be.calledWith(opts, this.project.cfg)166 })167 })168 it('calls #scaffold with server config promise', function () {169 return this.project.open().then(() => {170 expect(this.project.scaffold).to.be.calledWith(this.config)171 })172 })173 it('calls #checkSupportFile with server config when scaffolding is finished', function () {174 return this.project.open().then(() => {175 expect(this.project.checkSupportFile).to.be.calledWith(this.config)176 })177 })178 it('calls #getConfig options', function () {179 const opts = {}180 return this.project.open(opts).then(() => {181 expect(this.project.getConfig).to.be.calledWith(opts)182 })183 })184 it('initializes the plugins', function () {185 return this.project.open({}).then(() => {186 expect(plugins.init).to.be.called187 })188 })189 it('calls support.plugins with pluginsFile directory', function () {190 return this.project.open({}).then(() => {191 expect(scaffold.plugins).to.be.calledWith(path.dirname(this.config.pluginsFile))192 })193 })194 it('calls options.onError with plugins error when there is a plugins error', function () {195 const onError = sinon.spy()196 const err = {197 name: 'plugin error name',198 message: 'plugin error message',199 }200 return this.project.open({ onError }).then(() => {201 const pluginsOnError = plugins.init.lastCall.args[1].onError202 expect(pluginsOnError).to.be.a('function')203 pluginsOnError(err)204 expect(onError).to.be.calledWith(err)205 })206 })207 it('updates config.state when saved state changes', function () {208 sinon.spy(this.project, 'saveState')209 const options = {}210 return this.project.open(options)211 .then(() => options.onSavedStateChanged({ autoScrollingEnabled: false }))212 .then(() => this.project.getConfig())213 .then((config) => {214 expect(this.project.saveState).to.be.calledWith({ autoScrollingEnabled: false })215 expect(config.state).to.eql({ autoScrollingEnabled: false })216 })217 })218 // TODO: skip this for now219 it.skip('watches cypress.json', function () {220 return this.server.open().bind(this).then(() => {221 expect(Watchers.prototype.watch).to.be.calledWith('/Users/brian/app/cypress.json')222 })223 })224 // TODO: skip this for now225 it.skip('passes watchers to Socket.startListening', function () {226 const options = {}227 return this.server.open(options).then(() => {228 const { startListening } = SocketE2E.prototype229 expect(startListening.getCall(0).args[0]).to.be.instanceof(Watchers)230 expect(startListening.getCall(0).args[1]).to.eq(options)231 })232 })233 it('attaches warning to non-chrome browsers when chromeWebSecurity:false', function () {234 Object.assign(this.config, {235 browsers: [{ family: 'chromium', name: 'Canary' }, { family: 'some-other-family', name: 'some-other-name' }],236 chromeWebSecurity: false,237 })238 return this.project.open()239 .then(() => this.project.getConfig())240 .then((config) => {241 expect(config.chromeWebSecurity).eq(false)242 expect(config.browsers).deep.eq([243 {244 family: 'chromium',245 name: 'Canary',246 },247 {248 family: 'some-other-family',249 name: 'some-other-name',250 warning: `\251Your project has set the configuration option: \`chromeWebSecurity: false\`252This option will not have an effect in Some-other-name. Tests that rely on web security being disabled will not run as expected.\253`,254 },255 ])256 expect(config).ok257 })258 })259 })260 context('#close', () => {261 beforeEach(function () {262 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')263 sinon.stub(this.project, 'getConfig').resolves(this.config)264 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')265 })266 it('closes server', function () {267 this.project.server = sinon.stub({ close () {} })268 return this.project.close().then(() => {269 expect(this.project.server.close).to.be.calledOnce270 })271 })272 it('closes watchers', function () {273 this.project.watchers = sinon.stub({ close () {} })274 return this.project.close().then(() => {275 expect(this.project.watchers.close).to.be.calledOnce276 })277 })278 it('can close when server + watchers arent open', function () {279 return this.project.close()280 })281 })282 context('#reset', () => {283 beforeEach(function () {284 this.project = new ProjectE2E(this.pristinePath)285 this.project.automation = { reset: sinon.stub() }286 this.project.server = { reset: sinon.stub() }287 })288 it('resets server + automation', function () {289 return this.project.reset()290 .then(() => {291 expect(this.project.automation.reset).to.be.calledOnce292 expect(this.project.server.reset).to.be.calledOnce293 })294 })295 })296 context('#getRuns', () => {297 beforeEach(function () {298 this.project = new ProjectE2E(this.todosPath)299 sinon.stub(settings, 'read').resolves({ projectId: 'id-123' })300 sinon.stub(api, 'getProjectRuns').resolves('runs')301 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')302 })303 it('calls api.getProjectRuns with project id + session', function () {304 return this.project.getRuns().then((runs) => {305 expect(api.getProjectRuns).to.be.calledWith('id-123', 'auth-token-123')306 expect(runs).to.equal('runs')307 })308 })309 })310 context('#scaffold', () => {311 beforeEach(function () {312 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')313 sinon.stub(scaffold, 'integration').resolves()314 sinon.stub(scaffold, 'fixture').resolves()315 sinon.stub(scaffold, 'support').resolves()316 sinon.stub(scaffold, 'plugins').resolves()317 this.obj = { projectRoot: 'pr', fixturesFolder: 'ff', integrationFolder: 'if', supportFolder: 'sf', pluginsFile: 'pf/index.js' }318 })319 it('calls scaffold.integration with integrationFolder', function () {320 return this.project.scaffold(this.obj).then(() => {321 expect(scaffold.integration).to.be.calledWith(this.obj.integrationFolder)322 })323 })324 it('calls fixture.scaffold with fixturesFolder', function () {325 return this.project.scaffold(this.obj).then(() => {326 expect(scaffold.fixture).to.be.calledWith(this.obj.fixturesFolder)327 })328 })329 it('calls support.scaffold with supportFolder', function () {330 return this.project.scaffold(this.obj).then(() => {331 expect(scaffold.support).to.be.calledWith(this.obj.supportFolder)332 })333 })334 it('does not call support.plugins if config.pluginsFile is falsey', function () {335 this.obj.pluginsFile = false336 return this.project.scaffold(this.obj).then(() => {337 expect(scaffold.plugins).not.to.be.called338 })339 })340 describe('forced', () => {341 let resetEnv342 beforeEach(function () {343 this.obj.isTextTerminal = true344 resetEnv = mockedEnv({345 CYPRESS_INTERNAL_FORCE_SCAFFOLD: '1',346 })347 })348 afterEach(() => {349 resetEnv()350 })351 it('calls scaffold when forced by environment variable', function () {352 return this.project.scaffold(this.obj).then(() => {353 expect(scaffold.integration).to.be.calledWith(this.obj.integrationFolder)354 expect(scaffold.fixture).to.be.calledWith(this.obj.fixturesFolder)355 expect(scaffold.support).to.be.calledWith(this.obj.supportFolder)356 })357 })358 })359 describe('not forced', () => {360 let resetEnv361 beforeEach(function () {362 this.obj.isTextTerminal = true363 resetEnv = mockedEnv({364 CYPRESS_INTERNAL_FORCE_SCAFFOLD: undefined,365 })366 })367 afterEach(() => {368 resetEnv()369 })370 it('does not scaffold integration folder', function () {371 return this.project.scaffold(this.obj).then(() => {372 expect(scaffold.integration).to.not.be.calledWith(this.obj.integrationFolder)373 expect(scaffold.fixture).to.not.be.calledWith(this.obj.fixturesFolder)374 // still scaffolds support folder due to old logic375 expect(scaffold.support).to.be.calledWith(this.obj.supportFolder)376 })377 })378 })379 })380 context('#watchSettings', () => {381 beforeEach(function () {382 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')383 this.project.server = { startWebsockets () {} }384 sinon.stub(settings, 'pathToConfigFile').returns('/path/to/cypress.json')385 sinon.stub(settings, 'pathToCypressEnvJson').returns('/path/to/cypress.env.json')386 this.watch = sinon.stub(this.project.watchers, 'watch')387 })388 it('watches cypress.json and cypress.env.json', function () {389 this.project.watchSettingsAndStartWebsockets({ onSettingsChanged () {} })390 expect(this.watch).to.be.calledTwice391 expect(this.watch).to.be.calledWith('/path/to/cypress.json')392 expect(this.watch).to.be.calledWith('/path/to/cypress.env.json')393 })394 it('sets onChange event when {changeEvents: true}', function (done) {395 this.project.watchSettingsAndStartWebsockets({ onSettingsChanged: () => done() })396 // get the object passed to watchers.watch397 const obj = this.watch.getCall(0).args[1]398 expect(obj.onChange).to.be.a('function')399 obj.onChange()400 })401 it('does not call watch when {changeEvents: false}', function () {402 this.project.watchSettingsAndStartWebsockets({ onSettingsChanged: undefined })403 expect(this.watch).not.to.be.called404 })405 it('does not call onSettingsChanged when generatedProjectIdTimestamp is less than 1 second', function () {406 let timestamp = new Date()407 this.project.generatedProjectIdTimestamp = timestamp408 const stub = sinon.stub()409 this.project.watchSettingsAndStartWebsockets({ onSettingsChanged: stub })410 // get the object passed to watchers.watch411 const obj = this.watch.getCall(0).args[1]412 obj.onChange()413 expect(stub).not.to.be.called414 // subtract 1 second from our timestamp415 timestamp.setSeconds(timestamp.getSeconds() - 1)416 obj.onChange()417 expect(stub).to.be.calledOnce418 })419 })420 context('#checkSupportFile', () => {421 beforeEach(function () {422 sinon.stub(fs, 'pathExists').resolves(true)423 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')424 this.project.server = { onTestFileChange: sinon.spy() }425 sinon.stub(preprocessor, 'getFile').resolves()426 this.config = {427 projectRoot: '/path/to/root/',428 supportFile: '/path/to/root/foo/bar.js',429 }430 })431 it('does nothing when {supportFile: false}', function () {432 const ret = this.project.checkSupportFile({ supportFile: false })433 expect(ret).to.be.undefined434 })435 it('throws when support file does not exist', function () {436 fs.pathExists.resolves(false)437 return this.project.checkSupportFile(this.config)438 .catch((e) => {439 expect(e.message).to.include('The support file is missing or invalid.')440 })441 })442 })443 context('#watchPluginsFile', () => {444 beforeEach(function () {445 sinon.stub(fs, 'pathExists').resolves(true)446 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')447 this.project.watchers = { watchTree: sinon.spy() }448 sinon.stub(plugins, 'init').resolves()449 this.config = {450 pluginsFile: '/path/to/plugins-file',451 }452 })453 it('does nothing when {pluginsFile: false}', function () {454 this.config.pluginsFile = false455 return this.project.watchPluginsFile(this.config, {}).then(() => {456 expect(this.project.watchers.watchTree).not.to.be.called457 })458 })459 it('does nothing if pluginsFile does not exist', function () {460 fs.pathExists.resolves(false)461 return this.project.watchPluginsFile(this.config, {}).then(() => {462 expect(this.project.watchers.watchTree).not.to.be.called463 })464 })465 it('does nothing if in run mode', function () {466 return this.project.watchPluginsFile(this.config, {467 isTextTerminal: true,468 }).then(() => {469 expect(this.project.watchers.watchTree).not.to.be.called470 })471 })472 it('watches the pluginsFile', function () {473 return this.project.watchPluginsFile(this.config, {}).then(() => {474 expect(this.project.watchers.watchTree).to.be.calledWith(this.config.pluginsFile)475 expect(this.project.watchers.watchTree.lastCall.args[1]).to.be.an('object')476 expect(this.project.watchers.watchTree.lastCall.args[1].onChange).to.be.a('function')477 })478 })479 it('calls plugins.init when file changes', function () {480 return this.project.watchPluginsFile(this.config, {}).then(() => {481 this.project.watchers.watchTree.firstCall.args[1].onChange()482 expect(plugins.init).to.be.calledWith(this.config)483 })484 })485 it('handles errors from calling plugins.init', function (done) {486 const error = { name: 'foo', message: 'foo' }487 plugins.init.rejects(error)488 this.project.watchPluginsFile(this.config, {489 onError (err) {490 expect(err).to.eql(error)491 done()492 },493 })494 .then(() => {495 this.project.watchers.watchTree.firstCall.args[1].onChange()496 })497 })498 })499 context('#watchSettingsAndStartWebsockets', () => {500 beforeEach(function () {501 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')502 this.project.watchers = {}503 this.project.server = sinon.stub({ startWebsockets () {} })504 sinon.stub(this.project, 'watchSettings')505 sinon.stub(Automation, 'create').returns('automation')506 })507 it('calls server.startWebsockets with automation + config', function () {508 const c = {}509 this.project.watchSettingsAndStartWebsockets({}, c)510 expect(this.project.server.startWebsockets).to.be.calledWith('automation', c)511 })512 it('passes onReloadBrowser callback', function () {513 const fn = sinon.stub()514 this.project.server.startWebsockets.yieldsTo('onReloadBrowser')515 this.project.watchSettingsAndStartWebsockets({ onReloadBrowser: fn }, {})516 expect(fn).to.be.calledOnce517 })518 })519 context('#getProjectId', () => {520 beforeEach(function () {521 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')522 this.verifyExistence = sinon.stub(ProjectE2E.prototype, 'verifyExistence').resolves()523 })524 it('calls verifyExistence', function () {525 sinon.stub(settings, 'read').resolves({ projectId: 'id-123' })526 return this.project.getProjectId()527 .then(() => expect(this.verifyExistence).to.be.calledOnce)528 })529 it('returns the project id from settings', function () {530 sinon.stub(settings, 'read').resolves({ projectId: 'id-123' })531 return this.project.getProjectId()532 .then((id) => expect(id).to.eq('id-123'))533 })534 it('throws NO_PROJECT_ID with the projectRoot when no projectId was found', function () {535 sinon.stub(settings, 'read').resolves({})536 return this.project.getProjectId()537 .then((id) => {538 throw new Error('expected to fail, but did not')539 }).catch((err) => {540 expect(err.type).to.eq('NO_PROJECT_ID')541 expect(err.message).to.include('/_test-output/path/to/project-e2e')542 })543 })544 it('bubbles up Settings.read errors', function () {545 const err = new Error()546 err.code = 'EACCES'547 sinon.stub(settings, 'read').rejects(err)548 return this.project.getProjectId()549 .then((id) => {550 throw new Error('expected to fail, but did not')551 }).catch((err) => {552 expect(err.code).to.eq('EACCES')553 })554 })555 })556 context('#writeProjectId', () => {557 beforeEach(function () {558 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')559 sinon.stub(settings, 'write')560 .withArgs(this.project.projectRoot, { projectId: 'id-123' })561 .resolves({ projectId: 'id-123' })562 })563 it('calls Settings.write with projectRoot and attrs', function () {564 return this.project.writeProjectId('id-123').then((id) => {565 expect(id).to.eq('id-123')566 })567 })568 it('sets generatedProjectIdTimestamp', function () {569 return this.project.writeProjectId('id-123').then(() => {570 expect(this.project.generatedProjectIdTimestamp).to.be.a('date')571 })572 })573 })574 context('#getSpecUrl', () => {575 beforeEach(function () {576 this.project2 = new ProjectE2E(this.idsPath)577 return settings.write(this.idsPath, { port: 2020 })578 })579 it('returns fully qualified url when spec exists', function () {580 return this.project2.getSpecUrl('cypress/integration/bar.js')581 .then((str) => {582 expect(str).to.eq('http://localhost:2020/__/#/tests/integration/bar.js')583 })584 })585 it('returns fully qualified url on absolute path to spec', function () {586 const todosSpec = path.join(this.todosPath, 'tests/sub/sub_test.coffee')587 return this.project.getSpecUrl(todosSpec)588 .then((str) => {589 expect(str).to.eq('http://localhost:8888/__/#/tests/integration/sub/sub_test.coffee')590 })591 })592 it('escapses %, &', function () {593 const todosSpec = path.join(this.todosPath, 'tests/sub/a&b%c.js')594 return this.project.getSpecUrl(todosSpec)595 .then((str) => {596 expect(str).to.eq('http://localhost:8888/__/#/tests/integration/sub/a%26b%25c.js')597 })598 })599 // ? is invalid in Windows, but it can be tested here600 // because it's a unit test and doesn't check the existence of files601 it('escapes ?', function () {602 const todosSpec = path.join(this.todosPath, 'tests/sub/a?.spec.js')603 return this.project.getSpecUrl(todosSpec)604 .then((str) => {605 expect(str).to.eq('http://localhost:8888/__/#/tests/integration/sub/a%3F.spec.js')606 })607 })608 it('escapes %, &, ? in the url dir', function () {609 const todosSpec = path.join(this.todosPath, 'tests/s%&?ub/a.spec.js')610 return this.project.getSpecUrl(todosSpec)611 .then((str) => {612 expect(str).to.eq('http://localhost:8888/__/#/tests/integration/s%25%26%3Fub/a.spec.js')613 })614 })615 it('returns __all spec url', function () {616 return this.project.getSpecUrl()617 .then((str) => {618 expect(str).to.eq('http://localhost:8888/__/#/tests/__all')619 })620 })621 it('returns __all spec url with spec is __all', function () {622 return this.project.getSpecUrl('__all')623 .then((str) => {624 expect(str).to.eq('http://localhost:8888/__/#/tests/__all')625 })626 })627 })628 context('.add', () => {629 beforeEach(function () {630 this.pristinePath = Fixtures.projectPath('pristine')631 })632 it('inserts path into cache', function () {633 return ProjectE2E.add(this.pristinePath, {})634 .then(() => cache.read()).then((json) => {635 expect(json.PROJECTS).to.deep.eq([this.pristinePath])636 })637 })638 describe('if project at path has id', () => {639 it('returns object containing path and id', function () {640 sinon.stub(settings, 'read').resolves({ projectId: 'id-123' })641 return ProjectE2E.add(this.pristinePath, {})642 .then((project) => {643 expect(project.id).to.equal('id-123')644 expect(project.path).to.equal(this.pristinePath)645 })646 })647 })648 describe('if project at path does not have id', () => {649 it('returns object containing just the path', function () {650 sinon.stub(settings, 'read').rejects()651 return ProjectE2E.add(this.pristinePath, {})652 .then((project) => {653 expect(project.id).to.be.undefined654 expect(project.path).to.equal(this.pristinePath)655 })656 })657 })658 describe('if configFile is non-default', () => {659 it('doesn\'t cache anything and returns object containing just the path', function () {660 return ProjectE2E.add(this.pristinePath, { configFile: false })661 .then((project) => {662 expect(project.id).to.be.undefined663 expect(project.path).to.equal(this.pristinePath)664 return cache.read()665 }).then((json) => {666 expect(json.PROJECTS).to.deep.eq([])667 })668 })669 })670 })671 context('#createCiProject', () => {672 beforeEach(function () {673 this.project = new ProjectE2E('/_test-output/path/to/project-e2e')674 this.newProject = { id: 'project-id-123' }675 sinon.stub(this.project, 'writeProjectId').resolves('project-id-123')676 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')677 sinon.stub(commitInfo, 'getRemoteOrigin').resolves('remoteOrigin')678 sinon.stub(api, 'createProject')679 .withArgs({ foo: 'bar' }, 'remoteOrigin', 'auth-token-123')680 .resolves(this.newProject)681 })682 it('calls api.createProject with user session', function () {683 return this.project.createCiProject({ foo: 'bar' }).then(() => {684 expect(api.createProject).to.be.calledWith({ foo: 'bar' }, 'remoteOrigin', 'auth-token-123')685 })686 })687 it('calls writeProjectId with id', function () {688 return this.project.createCiProject({ foo: 'bar' }).then(() => {689 expect(this.project.writeProjectId).to.be.calledWith('project-id-123')690 })691 })692 it('returns project id', function () {693 return this.project.createCiProject({ foo: 'bar' }).then((projectId) => {694 expect(projectId).to.eql(this.newProject)695 })696 })697 })698 context('#getRecordKeys', () => {699 beforeEach(function () {700 this.recordKeys = []701 this.project = new ProjectE2E(this.pristinePath)702 sinon.stub(settings, 'read').resolves({ projectId: 'id-123' })703 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')704 sinon.stub(api, 'getProjectRecordKeys').resolves(this.recordKeys)705 })706 it('calls api.getProjectRecordKeys with project id + session', function () {707 return this.project.getRecordKeys().then(() => {708 expect(api.getProjectRecordKeys).to.be.calledWith('id-123', 'auth-token-123')709 })710 })711 it('returns ci keys', function () {712 return this.project.getRecordKeys().then((recordKeys) => {713 expect(recordKeys).to.equal(this.recordKeys)714 })715 })716 })717 context('#requestAccess', () => {718 beforeEach(function () {719 this.project = new ProjectE2E(this.pristinePath)720 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')721 sinon.stub(api, 'requestAccess').resolves('response')722 })723 it('calls api.requestAccess with project id + auth token', function () {724 return this.project.requestAccess('project-id-123').then(() => {725 expect(api.requestAccess).to.be.calledWith('project-id-123', 'auth-token-123')726 })727 })728 it('returns response', function () {729 return this.project.requestAccess('project-id-123').then((response) => {730 expect(response).to.equal('response')731 })732 })733 })734 context('.remove', () => {735 beforeEach(() => {736 sinon.stub(cache, 'removeProject').resolves()737 })738 it('calls cache.removeProject with path', () => {739 return ProjectE2E.remove('/_test-output/path/to/project-e2e').then(() => {740 expect(cache.removeProject).to.be.calledWith('/_test-output/path/to/project-e2e')741 })742 })743 })744 context('.id', () => {745 it('returns project id', function () {746 return ProjectE2E.id(this.todosPath).then((id) => {747 expect(id).to.eq(this.projectId)748 })749 })750 })751 context('.getOrgs', () => {752 beforeEach(() => {753 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')754 sinon.stub(api, 'getOrgs').resolves([])755 })756 it('calls api.getOrgs', () => {757 return ProjectE2E.getOrgs().then((orgs) => {758 expect(orgs).to.deep.eq([])759 expect(api.getOrgs).to.be.calledOnce760 expect(api.getOrgs).to.be.calledWith('auth-token-123')761 })762 })763 })764 context('.paths', () => {765 beforeEach(() => {766 sinon.stub(cache, 'getProjectRoots').resolves([])767 })768 it('calls cache.getProjectRoots', () => {769 return ProjectE2E.paths().then((ret) => {770 expect(ret).to.deep.eq([])771 expect(cache.getProjectRoots).to.be.calledOnce772 })773 })774 })775 context('.getPathsAndIds', () => {776 beforeEach(() => {777 sinon.stub(cache, 'getProjectRoots').resolves([778 '/path/to/first',779 '/path/to/second',780 ])781 sinon.stub(settings, 'id').resolves('id-123')782 })783 it('returns array of objects with paths and ids', () => {784 return ProjectE2E.getPathsAndIds().then((pathsAndIds) => {785 expect(pathsAndIds).to.eql([786 {787 path: '/path/to/first',788 id: 'id-123',789 },790 {791 path: '/path/to/second',792 id: 'id-123',793 },794 ])795 })796 })797 })798 context('.getProjectStatuses', () => {799 beforeEach(() => {800 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')801 })802 it('gets projects from api', () => {803 sinon.stub(api, 'getProjects').resolves([])804 return ProjectE2E.getProjectStatuses([])805 .then(() => {806 expect(api.getProjects).to.have.been.calledWith('auth-token-123')807 })808 })809 it('returns array of projects', () => {810 sinon.stub(api, 'getProjects').resolves([])811 return ProjectE2E.getProjectStatuses([])812 .then((projectsWithStatuses) => {813 expect(projectsWithStatuses).to.eql([])814 })815 })816 it('returns same number as client projects, even if there are less api projects', () => {817 sinon.stub(api, 'getProjects').resolves([])818 return ProjectE2E.getProjectStatuses([{}])819 .then((projectsWithStatuses) => {820 expect(projectsWithStatuses.length).to.eql(1)821 })822 })823 it('returns same number as client projects, even if there are more api projects', () => {824 sinon.stub(api, 'getProjects').resolves([{}, {}])825 return ProjectE2E.getProjectStatuses([{}])826 .then((projectsWithStatuses) => {827 expect(projectsWithStatuses.length).to.eql(1)828 })829 })830 it('merges in details of matching projects', () => {831 sinon.stub(api, 'getProjects').resolves([832 { id: 'id-123', lastBuildStatus: 'passing' },833 ])834 return ProjectE2E.getProjectStatuses([{ id: 'id-123', path: '/_test-output/path/to/project' }])835 .then((projectsWithStatuses) => {836 expect(projectsWithStatuses[0]).to.eql({837 id: 'id-123',838 path: '/_test-output/path/to/project',839 lastBuildStatus: 'passing',840 state: 'VALID',841 })842 })843 })844 it('returns client project when it has no id', () => {845 sinon.stub(api, 'getProjects').resolves([])846 return ProjectE2E.getProjectStatuses([{ path: '/_test-output/path/to/project' }])847 .then((projectsWithStatuses) => {848 expect(projectsWithStatuses[0]).to.eql({849 path: '/_test-output/path/to/project',850 state: 'VALID',851 })852 })853 })854 describe('when client project has id and there is no matching user project', () => {855 beforeEach(() => {856 sinon.stub(api, 'getProjects').resolves([])857 })858 it('marks project as invalid if api 404s', () => {859 sinon.stub(api, 'getProject').rejects({ name: '', message: '', statusCode: 404 })860 return ProjectE2E.getProjectStatuses([{ id: 'id-123', path: '/_test-output/path/to/project' }])861 .then((projectsWithStatuses) => {862 expect(projectsWithStatuses[0]).to.eql({863 id: 'id-123',864 path: '/_test-output/path/to/project',865 state: 'INVALID',866 })867 })868 })869 it('marks project as unauthorized if api 403s', () => {870 sinon.stub(api, 'getProject').rejects({ name: '', message: '', statusCode: 403 })871 return ProjectE2E.getProjectStatuses([{ id: 'id-123', path: '/_test-output/path/to/project' }])872 .then((projectsWithStatuses) => {873 expect(projectsWithStatuses[0]).to.eql({874 id: 'id-123',875 path: '/_test-output/path/to/project',876 state: 'UNAUTHORIZED',877 })878 })879 })880 it('merges in project details and marks valid if somehow project exists and is authorized', () => {881 sinon.stub(api, 'getProject').resolves({ id: 'id-123', lastBuildStatus: 'passing' })882 return ProjectE2E.getProjectStatuses([{ id: 'id-123', path: '/_test-output/path/to/project' }])883 .then((projectsWithStatuses) => {884 expect(projectsWithStatuses[0]).to.eql({885 id: 'id-123',886 path: '/_test-output/path/to/project',887 lastBuildStatus: 'passing',888 state: 'VALID',889 })890 })891 })892 it('throws error if not accounted for', () => {893 const error = { name: '', message: '' }894 sinon.stub(api, 'getProject').rejects(error)895 return ProjectE2E.getProjectStatuses([{ id: 'id-123', path: '/_test-output/path/to/project' }])896 .then(() => {897 throw new Error('should have caught error but did not')898 }).catch((err) => {899 expect(err).to.equal(error)900 })901 })902 })903 })904 context('.getProjectStatus', () => {905 beforeEach(function () {906 this.clientProject = {907 id: 'id-123',908 path: '/_test-output/path/to/project',909 }910 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')911 })912 it('gets project from api', function () {913 sinon.stub(api, 'getProject').resolves([])914 return ProjectE2E.getProjectStatus(this.clientProject)915 .then(() => {916 expect(api.getProject).to.have.been.calledWith('id-123', 'auth-token-123')917 })918 })919 it('returns project merged with details', function () {920 sinon.stub(api, 'getProject').resolves({921 lastBuildStatus: 'passing',922 })923 return ProjectE2E.getProjectStatus(this.clientProject)924 .then((project) => {925 expect(project).to.eql({926 id: 'id-123',927 path: '/_test-output/path/to/project',928 lastBuildStatus: 'passing',929 state: 'VALID',930 })931 })932 })933 it('returns project, marked as valid, if it does not have an id, without querying api', function () {934 sinon.stub(api, 'getProject')935 this.clientProject.id = undefined936 return ProjectE2E.getProjectStatus(this.clientProject)937 .then((project) => {938 expect(project).to.eql({939 id: undefined,940 path: '/_test-output/path/to/project',941 state: 'VALID',942 })943 expect(api.getProject).not.to.be.called944 })945 })946 it('marks project as invalid if api 404s', function () {947 sinon.stub(api, 'getProject').rejects({ name: '', message: '', statusCode: 404 })948 return ProjectE2E.getProjectStatus(this.clientProject)949 .then((project) => {950 expect(project).to.eql({951 id: 'id-123',952 path: '/_test-output/path/to/project',953 state: 'INVALID',954 })955 })956 })957 it('marks project as unauthorized if api 403s', function () {958 sinon.stub(api, 'getProject').rejects({ name: '', message: '', statusCode: 403 })959 return ProjectE2E.getProjectStatus(this.clientProject)960 .then((project) => {961 expect(project).to.eql({962 id: 'id-123',963 path: '/_test-output/path/to/project',964 state: 'UNAUTHORIZED',965 })966 })967 })968 it('throws error if not accounted for', function () {969 const error = { name: '', message: '' }970 sinon.stub(api, 'getProject').rejects(error)971 return ProjectE2E.getProjectStatus(this.clientProject)972 .then(() => {973 throw new Error('should have caught error but did not')974 }).catch((err) => {975 expect(err).to.equal(error)976 })977 })978 })979 context('.getSecretKeyByPath', () => {980 beforeEach(() => {981 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')982 })983 it('calls api.getProjectToken with id + session', function () {984 sinon.stub(api, 'getProjectToken')985 .withArgs(this.projectId, 'auth-token-123')986 .resolves('key-123')987 return ProjectE2E.getSecretKeyByPath(this.todosPath).then((key) => {988 expect(key).to.eq('key-123')989 })990 })991 it('throws CANNOT_FETCH_PROJECT_TOKEN on error', function () {992 sinon.stub(api, 'getProjectToken')993 .withArgs(this.projectId, 'auth-token-123')994 .rejects(new Error())995 return ProjectE2E.getSecretKeyByPath(this.todosPath)996 .then(() => {997 throw new Error('should have caught error but did not')998 }).catch((err) => {999 expect(err.type).to.eq('CANNOT_FETCH_PROJECT_TOKEN')1000 })1001 })1002 })1003 context('.generateSecretKeyByPath', () => {1004 beforeEach(() => {1005 sinon.stub(user, 'ensureAuthToken').resolves('auth-token-123')1006 })1007 it('calls api.updateProjectToken with id + session', function () {1008 sinon.stub(api, 'updateProjectToken')1009 .withArgs(this.projectId, 'auth-token-123')1010 .resolves('new-key-123')1011 return ProjectE2E.generateSecretKeyByPath(this.todosPath).then((key) => {1012 expect(key).to.eq('new-key-123')1013 })1014 })1015 it('throws CANNOT_CREATE_PROJECT_TOKEN on error', function () {1016 sinon.stub(api, 'updateProjectToken')1017 .withArgs(this.projectId, 'auth-token-123')1018 .rejects(new Error())1019 return ProjectE2E.generateSecretKeyByPath(this.todosPath)1020 .then(() => {1021 throw new Error('should have caught error but did not')1022 }).catch((err) => {1023 expect(err.type).to.eq('CANNOT_CREATE_PROJECT_TOKEN')1024 })1025 })1026 })...
project.js
Source:project.js
...122 }123 });124 };125 Project.prototype.getRuns = function() {126 return Promise.all([this.getProjectId(), user.ensureAuthToken()]).spread(function(projectId, authToken) {127 return api.getProjectRuns(projectId, authToken);128 });129 };130 Project.prototype.reset = function() {131 debug("resetting project instance %s", this.projectRoot);132 this.spec = this.browser = null;133 return Promise["try"]((function(_this) {134 return function() {135 var ref, ref1;136 if ((ref = _this.automation) != null) {137 ref.reset();138 }139 return (ref1 = _this.server) != null ? ref1.reset() : void 0;140 };141 })(this));142 };143 Project.prototype.close = function() {144 var ref, ref1;145 debug("closing project instance %s", this.projectRoot);146 if (this.memoryCheck) {147 clearInterval(this.memoryCheck);148 }149 this.cfg = this.spec = this.browser = null;150 return Promise.join((ref = this.server) != null ? ref.close() : void 0, (ref1 = this.watchers) != null ? ref1.close() : void 0, preprocessor.close()).then(function() {151 return process.chdir(localCwd);152 });153 };154 Project.prototype.checkSupportFile = function(cfg) {155 var supportFile;156 if (supportFile = cfg.supportFile) {157 return fs.pathExists(supportFile).then((function(_this) {158 return function(found) {159 if (!found) {160 return errors["throw"]("SUPPORT_FILE_NOT_FOUND", supportFile);161 }162 };163 })(this));164 }165 };166 Project.prototype.watchPluginsFile = function(cfg, options) {167 debug("attempt watch plugins file: " + cfg.pluginsFile);168 if (!cfg.pluginsFile) {169 return Promise.resolve();170 }171 return fs.pathExists(cfg.pluginsFile).then((function(_this) {172 return function(found) {173 debug("plugins file found? " + found);174 if (!found) {175 return;176 }177 debug("watch plugins file");178 return _this.watchers.watchTree(cfg.pluginsFile, {179 onChange: function() {180 debug("plugins file changed");181 return _this._initPlugins(cfg, options)["catch"](function(err) {182 return options.onError(err);183 });184 }185 });186 };187 })(this));188 };189 Project.prototype.watchSettings = function(onSettingsChanged) {190 var obj;191 if (!onSettingsChanged) {192 return;193 }194 debug("watch settings files");195 obj = {196 onChange: (function(_this) {197 return function(filePath, stats) {198 if (_this.generatedProjectIdTimestamp && (new Date - _this.generatedProjectIdTimestamp) < 1000) {199 return;200 }201 return onSettingsChanged.call(_this);202 };203 })(this)204 };205 this.watchers.watch(settings.pathToCypressJson(this.projectRoot), obj);206 return this.watchers.watch(settings.pathToCypressEnvJson(this.projectRoot), obj);207 };208 Project.prototype.watchSettingsAndStartWebsockets = function(options, cfg) {209 var err, errorMsg, paths, projectRoot, reporter;210 if (options == null) {211 options = {};212 }213 if (cfg == null) {214 cfg = {};215 }216 this.watchSettings(options.onSettingsChanged);217 reporter = cfg.reporter, projectRoot = cfg.projectRoot;218 if (cfg.report) {219 try {220 Reporter.loadReporter(reporter, projectRoot);221 } catch (error) {222 err = error;223 paths = Reporter.getSearchPathsForReporter(reporter, projectRoot);224 errorMsg = err.code === "MODULE_NOT_FOUND" ? err.message : err.stack;225 errors["throw"]("INVALID_REPORTER_NAME", {226 paths: paths,227 error: errorMsg,228 name: reporter229 });230 }231 reporter = Reporter.create(reporter, cfg.reporterOptions, projectRoot);232 }233 this.automation = Automation.create(cfg.namespace, cfg.socketIoCookie, cfg.screenshotsFolder);234 return this.server.startWebsockets(this.automation, cfg, {235 onReloadBrowser: options.onReloadBrowser,236 onFocusTests: options.onFocusTests,237 onSpecChanged: options.onSpecChanged,238 onSavedStateChanged: options.onSavedStateChanged,239 onConnect: (function(_this) {240 return function(id) {241 return _this.emit("socket:connected", id);242 };243 })(this),244 onSetRunnables: function(runnables) {245 debug("received runnables %o", runnables);246 return reporter != null ? reporter.setRunnables(runnables) : void 0;247 },248 onMocha: (function(_this) {249 return function(event, runnable) {250 debug("onMocha", event);251 if (!reporter) {252 return;253 }254 reporter.emit(event, runnable);255 if (event === "end") {256 return Promise.all([reporter != null ? reporter.end() : void 0, _this.server.end()]).spread(function(stats) {257 if (stats == null) {258 stats = {};259 }260 return _this.emit("end", stats);261 });262 }263 };264 })(this)265 });266 };267 Project.prototype.changeToUrl = function(url) {268 return this.server.changeToUrl(url);269 };270 Project.prototype.setCurrentSpecAndBrowser = function(spec, browser) {271 this.spec = spec;272 return this.browser = browser;273 };274 Project.prototype.getCurrentSpecAndBrowser = function() {275 return _.pick(this, "spec", "browser");276 };277 Project.prototype.setBrowsers = function(browsers) {278 if (browsers == null) {279 browsers = [];280 }281 return this.getConfig().then(function(cfg) {282 return cfg.browsers = browsers;283 });284 };285 Project.prototype.getAutomation = function() {286 return this.automation;287 };288 Project.prototype.determineIsNewProject = function(folder) {289 return scaffold.isNewProject(folder);290 };291 Project.prototype.getConfig = function(options) {292 var setNewProject;293 if (options == null) {294 options = {};295 }296 if (this.cfg) {297 return Promise.resolve(this.cfg);298 }299 setNewProject = (function(_this) {300 return function(cfg) {301 if (cfg.isTextTerminal) {302 return;303 }304 if (!cfg.integrationFolder) {305 throw new Error("Missing integration folder");306 }307 return _this.determineIsNewProject(cfg.integrationFolder).then(function(untouchedScaffold) {308 var userHasSeenOnBoarding;309 userHasSeenOnBoarding = _.get(cfg, 'state.showedOnBoardingModal', false);310 scaffoldDebug("untouched scaffold " + untouchedScaffold + " modal closed " + userHasSeenOnBoarding);311 return cfg.isNewProject = untouchedScaffold && !userHasSeenOnBoarding;312 });313 };314 })(this);315 return config.get(this.projectRoot, options).then((function(_this) {316 return function(cfg) {317 return _this._setSavedState(cfg);318 };319 })(this)).tap(setNewProject);320 };321 Project.prototype.saveState = function(stateChanges) {322 var newState;323 if (stateChanges == null) {324 stateChanges = {};325 }326 if (!this.cfg) {327 throw new Error("Missing project config");328 }329 if (!this.projectRoot) {330 throw new Error("Missing project root");331 }332 newState = _.merge({}, this.cfg.state, stateChanges);333 return savedState(this.projectRoot, this.cfg.isTextTerminal).then(function(state) {334 return state.set(newState);335 }).then((function(_this) {336 return function() {337 _this.cfg.state = newState;338 return newState;339 };340 })(this));341 };342 Project.prototype._setSavedState = function(cfg) {343 debug("get saved state");344 return savedState(this.projectRoot, cfg.isTextTerminal).then(function(state) {345 return state.get();346 }).then(function(state) {347 cfg.state = state;348 return cfg;349 });350 };351 Project.prototype.getSpecUrl = function(absoluteSpecPath) {352 return this.getConfig().then((function(_this) {353 return function(cfg) {354 var prefixedPath;355 if (!absoluteSpecPath || (absoluteSpecPath === "__all")) {356 return _this.normalizeSpecUrl(cfg.browserUrl, "/__all");357 } else {358 prefixedPath = _this.getPrefixedPathToSpec(cfg, absoluteSpecPath);359 return _this.normalizeSpecUrl(cfg.browserUrl, prefixedPath);360 }361 };362 })(this));363 };364 Project.prototype.getPrefixedPathToSpec = function(cfg, pathToSpec, type) {365 var integrationFolder, projectRoot;366 if (type == null) {367 type = "integration";368 }369 integrationFolder = cfg.integrationFolder, projectRoot = cfg.projectRoot;370 return "/" + path.join(type, path.relative(integrationFolder, path.resolve(projectRoot, pathToSpec)));371 };372 Project.prototype.normalizeSpecUrl = function(browserUrl, specUrl) {373 var replacer;374 replacer = function(match, p1) {375 return match.replace("//", "/");376 };377 return [browserUrl, "#/tests", specUrl].join("/").replace(multipleForwardSlashesRe, replacer);378 };379 Project.prototype.scaffold = function(cfg) {380 var push, scaffolds;381 debug("scaffolding project %s", this.projectRoot);382 scaffolds = [];383 push = scaffolds.push.bind(scaffolds);384 push(scaffold.support(cfg.supportFolder, cfg));385 if (!cfg.isTextTerminal) {386 push(scaffold.integration(cfg.integrationFolder, cfg));387 push(scaffold.fixture(cfg.fixturesFolder, cfg));388 }389 return Promise.all(scaffolds);390 };391 Project.prototype.writeProjectId = function(id) {392 var attrs;393 attrs = {394 projectId: id395 };396 logger.info("Writing Project ID", _.clone(attrs));397 this.generatedProjectIdTimestamp = new Date;398 return settings.write(this.projectRoot, attrs)["return"](id);399 };400 Project.prototype.getProjectId = function() {401 return this.verifyExistence().then((function(_this) {402 return function() {403 return settings.read(_this.projectRoot);404 };405 })(this)).then((function(_this) {406 return function(settings) {407 var id;408 if (settings && (id = settings.projectId)) {409 return id;410 }411 return errors["throw"]("NO_PROJECT_ID", _this.projectRoot);412 };413 })(this));414 };415 Project.prototype.verifyExistence = function() {416 return fs.statAsync(this.projectRoot)["return"](this)["catch"]((function(_this) {417 return function() {418 return errors["throw"]("NO_PROJECT_FOUND_AT_PROJECT_ROOT", _this.projectRoot);419 };420 })(this));421 };422 Project.prototype.createCiProject = function(projectDetails) {423 return user.ensureAuthToken().then((function(_this) {424 return function(authToken) {425 return commitInfo.getRemoteOrigin(_this.projectRoot).then(function(remoteOrigin) {426 return api.createProject(projectDetails, remoteOrigin, authToken);427 });428 };429 })(this)).then((function(_this) {430 return function(newProject) {431 return _this.writeProjectId(newProject.id)["return"](newProject);432 };433 })(this));434 };435 Project.prototype.getRecordKeys = function() {436 return Promise.all([this.getProjectId(), user.ensureAuthToken()]).spread(function(projectId, authToken) {437 return api.getProjectRecordKeys(projectId, authToken);438 });439 };440 Project.prototype.requestAccess = function(projectId) {441 return user.ensureAuthToken().then(function(authToken) {442 return api.requestAccess(projectId, authToken);443 });444 };445 Project.getOrgs = function() {446 return user.ensureAuthToken().then(function(authToken) {447 return api.getOrgs(authToken);448 });449 };450 Project.paths = function() {451 return cache.getProjectRoots();452 };453 Project.getPathsAndIds = function() {454 return cache.getProjectRoots().map(function(projectRoot) {455 return Promise.props({456 path: projectRoot,457 id: settings.id(projectRoot)458 });459 });460 };461 Project._mergeDetails = function(clientProject, project) {462 return _.extend({}, clientProject, project, {463 state: "VALID"464 });465 };466 Project._mergeState = function(clientProject, state) {467 return _.extend({}, clientProject, {468 state: state469 });470 };471 Project._getProject = function(clientProject, authToken) {472 debug("get project from api", clientProject.id, clientProject.path);473 return api.getProject(clientProject.id, authToken).then(function(project) {474 debug("got project from api");475 return Project._mergeDetails(clientProject, project);476 })["catch"](function(err) {477 debug("failed to get project from api", err.statusCode);478 switch (err.statusCode) {479 case 404:480 return Project._mergeState(clientProject, "INVALID");481 case 403:482 return Project._mergeState(clientProject, "UNAUTHORIZED");483 default:484 throw err;485 }486 });487 };488 Project.getProjectStatuses = function(clientProjects) {489 if (clientProjects == null) {490 clientProjects = [];491 }492 debug("get project statuses for " + clientProjects.length + " projects");493 return user.ensureAuthToken().then(function(authToken) {494 debug("got auth token " + authToken);495 return api.getProjects(authToken).then(function(projects) {496 var projectsIndex;497 if (projects == null) {498 projects = [];499 }500 debug("got " + projects.length + " projects");501 projectsIndex = _.keyBy(projects, "id");502 return Promise.all(_.map(clientProjects, function(clientProject) {503 var project;504 debug("looking at", clientProject.path);505 if (!clientProject.id) {506 debug("no project id");507 return Project._mergeState(clientProject, "VALID");508 }509 if (project = projectsIndex[clientProject.id]) {510 debug("found matching:", project);511 return Project._mergeDetails(clientProject, project);512 } else {513 debug("did not find matching:", project);514 return Project._getProject(clientProject, authToken);515 }516 }));517 });518 });519 };520 Project.getProjectStatus = function(clientProject) {521 debug("get project status for", clientProject.id, clientProject.path);522 if (!clientProject.id) {523 debug("no project id");524 return Promise.resolve(Project._mergeState(clientProject, "VALID"));525 }526 return user.ensureAuthToken().then(function(authToken) {527 debug("got auth token " + authToken);528 return Project._getProject(clientProject, authToken);529 });530 };531 Project.remove = function(path) {532 return cache.removeProject(path);533 };534 Project.add = function(path) {535 return cache.insertProject(path).then((function(_this) {536 return function() {537 return _this.id(path);538 };539 })(this)).then(function(id) {540 return {541 id: id,542 path: path543 };544 })["catch"](function() {545 return {546 path: path547 };548 });549 };550 Project.id = function(path) {551 return Project(path).getProjectId();552 };553 Project.ensureExists = function(path) {554 return settings.exists(path);555 };556 Project.config = function(path) {557 return Project(path).getConfig();558 };559 Project.getSecretKeyByPath = function(path) {560 return Project.id(path).then(function(id) {561 return user.ensureAuthToken().then(function(authToken) {562 return api.getProjectToken(id, authToken)["catch"](function() {563 return errors["throw"]("CANNOT_FETCH_PROJECT_TOKEN");564 });565 });566 });567 };568 Project.generateSecretKeyByPath = function(path) {569 return Project.id(path).then(function(id) {570 return user.ensureAuthToken().then(function(authToken) {571 return api.updateProjectToken(id, authToken)["catch"](function() {572 return errors["throw"]("CANNOT_CREATE_PROJECT_TOKEN");573 });574 });575 });576 };577 Project.findSpecs = function(projectRoot, specPattern) {578 debug("finding specs for project %s", projectRoot);579 la(check.unemptyString(projectRoot), "missing project path", projectRoot);580 la(check.maybe.unemptyString(specPattern), "invalid spec pattern", specPattern);581 if (specPattern) {582 specPattern = path.resolve(projectRoot, specPattern);583 }584 return Project(projectRoot).getConfig().then(function(cfg) {...
user_spec.js
Source:user_spec.js
...69 })70 context('.ensureAuthToken', () => {71 it('returns authToken', () => {72 sinon.stub(cache, 'getUser').resolves({ name: 'brian', authToken: 'abc-123' })73 return user.ensureAuthToken().then((st) => {74 expect(st).to.eq('abc-123')75 })76 })77 it('throws NOT_LOGGED_IN when no authToken, tagged as api error', () => {78 sinon.stub(cache, 'getUser').resolves(null)79 return user.ensureAuthToken()80 .then(() => {81 throw new Error('should have thrown an error')82 }).catch((err) => {83 const expectedErr = errors.get('NOT_LOGGED_IN')84 expect(err.message).to.eq(expectedErr.message)85 expect(err.isApiError).to.be.true86 expect(err.type).to.eq(expectedErr.type)87 })88 })89 })...
user.js
Source:user.js
1const debug = require('debug')('cypress:server:user')2const api = require('./api')3const cache = require('./cache')4const errors = require('./errors')5const keys = require('./util/keys')6module.exports = {7 get () {8 return cache.getUser()9 },10 getSafely () {11 return this.get()12 .tap((user) => {13 if (user.authToken) {14 user.authToken = keys.hide(user.authToken)15 }16 })17 },18 set (user) {19 return cache.setUser(user)20 },21 getBaseLoginUrl () {22 return api.getAuthUrls()23 .get('dashboardAuthUrl')24 },25 logOut () {26 return this.get().then((user) => {27 const authToken = user && user.authToken28 return cache.removeUser().then(() => {29 if (authToken) {30 return api.postLogout(authToken)31 }32 })33 })34 },35 syncProfile (authToken) {36 debug('synchronizing user profile')37 return api.getMe(authToken)38 .then((res) => {39 debug('received /me %o', res)40 const user = {41 authToken,42 name: res.name,43 email: res.email,44 }45 return this.set(user)46 .return(user)47 })48 },49 ensureAuthToken () {50 return this.get().then((user) => {51 // return authToken if we have one52 let at53 if (user && (at = user.authToken)) {54 debug('found authToken %s', at)55 return at56 }57 // else throw the not logged in error58 const error = errors.get('NOT_LOGGED_IN')59 // tag it as api error since the user is only relevant60 // in regards to the api61 error.isApiError = true62 throw error63 })64 },...
Using AI Code Generation
1Cypress.Commands.add('login', (email, password) => {2 cy.request({3 body: {4 }5 }).then((response) => {6 window.localStorage.setItem('authToken', response.body.token);7 });8});9Cypress.Commands.add('logout', () => {10 cy.request({11 }).then(() => {12 window.localStorage.removeItem('authToken');13 });14});15describe('My First Test', function() {16 it('Does not do much!', function() {17 });18});19describe('My First Test', function() {20 it('Does not do much!', function() {21 });22 it('Logs in', function() {23 cy.login('
Cypress is a renowned Javascript-based open-source, easy-to-use end-to-end testing framework primarily used for testing web applications. Cypress is a relatively new player in the automation testing space and has been gaining much traction lately, as evidenced by the number of Forks (2.7K) and Stars (42.1K) for the project. LambdaTest’s Cypress Tutorial covers step-by-step guides that will help you learn from the basics till you run automation tests on LambdaTest.
You can elevate your expertise with end-to-end testing using the Cypress automation framework and stay one step ahead in your career by earning a Cypress certification. Check out our Cypress 101 Certification.
Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.
Get 100 minutes of automation test minutes FREE!!