How to use cache.getProjectRoots method in Cypress

Best JavaScript code snippet using cypress

project_spec.js

Source:project_spec.js Github

copy

Full Screen

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  })...

Full Screen

Full Screen

project.js

Source:project.js Github

copy

Full Screen

...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: state...

Full Screen

Full Screen

cache_spec.js

Source:cache_spec.js Github

copy

Full Screen

...118        return cache.insertProject('/Users/brian/app')119        .then(() => {120          return cache.insertProject('/Users/sam/app2')121        }).then(() => {122          return cache.getProjectRoots().then((paths) => {123            expect(paths).to.deep.eq(['/Users/sam/app2', '/Users/brian/app'])124          })125        })126      })127      it('removes any paths which no longer exist on the filesystem', function () {128        this.statAsync.withArgs('/Users/brian/app').resolves()129        this.statAsync.withArgs('/Users/sam/app2').rejects(new Error())130        return cache.insertProject('/Users/brian/app')131        .then(() => {132          return cache.insertProject('/Users/sam/app2')133        }).then(() => {134          return cache.getProjectRoots().then((paths) => {135            expect(paths).to.deep.eq(['/Users/brian/app'])136          })137        })138        .then(() => {139          // we have to wait on the write event because140          // of process.nextTick141          return Promise.delay(100).then(() => {142            return cache.__get('PROJECTS').then((projects) => {143              expect(projects).to.deep.eq(['/Users/brian/app'])144            })145          })146        })147      })148    })...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', function() {2  it('Does not do much!', function() {3    cy.contains('type').click();4    cy.url().should('include', '/commands/actions');5    cy.get('.action-email')6      .type('

Full Screen

Using AI Code Generation

copy

Full Screen

1Cypress. cache . getProjectRoots (). then (( roots ) => {2console . log ( roots );3})4Cypress. cache . getCacheFolder (). then (( folder ) => {5console . log ( folder );6})7Cypress. cache . getCacheFilePath ( 'test' ). then (( filePath ) => {8console . log ( filePath );9})10Cypress. cache . getCachePath ( 'test' ). then (( path ) => {11console . log ( path );12})13Cypress. cache . getCache ( 'test' ). then (( cache ) => {14console . log ( cache );15})16Cypress. cache . setCache ( 'test' , { "name" : "Cypress" }). then (() => {17console . log ( 'cache is set' );18})19Cypress. cache . clearCache ( 'test' ). then (() => {20console . log ( 'cache is cleared' );21})22Cypress. cache . clearAllCache (). then (() => {23console . log ( 'all cache is cleared' );24})25Cypress. cache . deleteCache ( 'test' ). then (() => {26console . log ( 'cache is deleted' );27})28Cypress. cache . deleteAllCache (). then (() => {29console . log ( 'all cache is deleted' );30})31Cypress. cache . addCache ( 'test' , { "name" : "Cypress" }). then (() => {32console . log ( 'cache is added' );33})34Cypress. cache . addCache ( 'test' , { "name" : "Cypress" }). then (() => {35console . log ( 'cache is added' );36})37Cypress. cache . addCache ( 'test' , { "name" : "Cypress" }). then (() =>

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('Test', () => {2    it('test', () => {3        cy.log(cy.cache.getProjectRoots());4    });5});6module.exports = (on, config) => {7    on('task', {8        getProjectRoots() {9            return Cypress.config('projectRoots');10        }11    });12};13Cypress.Commands.add('cache', {14    getProjectRoots() {15        return cy.task('getProjectRoots');16    }17});18Cypress.Commands.add('cache', {19    getProjectRoots() {20        return cy.task('getProjectRoots');21    }22});

Full Screen

Using AI Code Generation

copy

Full Screen

1Cypress . cache . getProjectRoots (). then (( roots ) => { 2   console . log ( roots ) 3 })4Cypress . cache . clear () 5 Cypress . cache . clear ( 'localhost' ) 6 Cypress . cache . clear ( 'localhost' ,   'index.html' )7Cypress . cache . get ( 'localhost' ,   'index.html' )8Cypress . cache . put ( 'localhost' ,   'index.html' ,   'html content' )9Cypress . cache . remove ( 'localhost' ) 10 Cypress . cache . remove ( 'localhost' ,   'index.html' )11Cypress . cache . list (). then (( list ) => { 12   console . log ( list ) 13 })14Cypress . cache . list ( 'localhost' ). then (( list ) => { 15   console . log ( list ) 16 })17Cypress . cache . keys (). then (( keys ) => { 18   console . log ( keys ) 19 })20Cypress . cache . keys ( 'localhost' ). then (( keys ) => { 21   console . log ( keys ) 22 })23Cypress . cache . has ( 'localhost' ). then (( has ) => { 24   console . log ( has ) 25 })26Cypress . cache . has ( 'localhost' ,   'index.html' ). then (( has ) => { 27   console . log ( has ) 28 })29Cypress . cache . size (). then (( size ) => { 30   console . log ( size ) 31 })32Cypress . cache . size ( 'localhost' ). then (( size ) => { 33   console . log ( size ) 34 })35Cypress . cache . getProjectRoots (). then (( roots ) => { 36   console . log ( roots ) 37 })38Cypress . cache . clear () 39 Cypress . cache . clear ( 'localhost' ) 40 Cypress . cache . clear ( 'localhost' ,   'index.html' )41Cypress . cache . get ( 'localhost' ,   'index.html' )42Cypress . cache . put ( 'localhost' ,   'index.html' ,   'html content' )43Cypress . cache . remove ( 'localhost' ) 44 Cypress . cache . remove ( 'localhost' ,   'index.html' )45Cypress . cache . list (). then (( list ) => { 46   console . log ( list ) 47 })

Full Screen

Using AI Code Generation

copy

Full Screen

1const cache = require('@packages/server/lib/util/cache')2const projectRoots = cache.getProjectRoots()3console.log(projectRoots)4const getProjectRoots = () => projectRoots5module.exports = {6}7const getProjectRoots = () => projectRoots8module.exports = {9}10const projectRoots = cache.getProjectRoots()11console.log(projectRoots)12const projectRoots = cache.getProjectRoots()13console.log(projectRoots)

Full Screen

Using AI Code Generation

copy

Full Screen

1const cache = require('@packages/server/lib/util/cache')2const projectRoots = cache.getProjectRoots()3console.log(projectRoots)4const cache = require('@packages/server/lib/util/cache')5const projectRoots = cache.getProjectRoots()6console.log(projectRoots)

Full Screen

Using AI Code Generation

copy

Full Screen

1const cache = require('@packages/server/lib/util/cache')2cache.getProjectRoots()3{4}5### `cache.clearProjectRoots ()`6## `cache.getSpecs (projectRoot)`7const cache = require('@packages/server/lib/util/cache')8cache.getSpecs('path/to/project')9{10  'path/to/project': {11  }12}13### `cache.clearSpecs (projectRoot)`14const cache = require('@packages/server/lib/util/cache')15cache.clearSpecs('path/to/project')16## `cache.getSpec (projectRoot, spec)`17const cache = require('@packages/server/lib/util/cache')18cache.getSpec('path/to/project', 'path/to/spec')

Full Screen

Using AI Code Generation

copy

Full Screen

1const { cache } = require("cypress");2const rootPath = cache.getProjectRoots();3console.log(rootPath);4const { cache } = require("cypress");5const rootPath = cache.getProjectRoots("project name");6console.log(rootPath);

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypressCache = require('cypress-cache')2const cache = new cypressCache()3cache.getProjectRoots().then((roots) => {4})5{6  "baseUrl": "cache.getProjectRoots()"7}8{9  "baseUrl": "cache.getProjectRoots().then((roots) => {10})"11}12How can I use the cache.getProjectRoots() method of Cypress in the cypress.json file?

Full Screen

Cypress Tutorial

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.

Chapters:

  1. What is Cypress? -
  2. Why Cypress? - Learn why Cypress might be a good choice for testing your web applications.
  3. Features of Cypress Testing - Learn about features that make Cypress a powerful and flexible tool for testing web applications.
  4. Cypress Drawbacks - Although Cypress has many strengths, it has a few limitations that you should be aware of.
  5. Cypress Architecture - Learn more about Cypress architecture and how it is designed to be run directly in the browser, i.e., it does not have any additional servers.
  6. Browsers Supported by Cypress - Cypress is built on top of the Electron browser, supporting all modern web browsers. Learn browsers that support Cypress.
  7. Selenium vs Cypress: A Detailed Comparison - Compare and explore some key differences in terms of their design and features.
  8. Cypress Learning: Best Practices - Take a deep dive into some of the best practices you should use to avoid anti-patterns in your automation tests.
  9. How To Run Cypress Tests on LambdaTest? - Set up a LambdaTest account, and now you are all set to learn how to run Cypress tests.

Certification

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.

YouTube

Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful