text: const express = require('express')
  const app = express()
  const chai = require('chai')
  const expect = chai.expect
  chai.use(require('chai-http'))
  
  // Body Parser Middleware
  app.use(express.json()) // Allows us to handle raw JSON data
  app.use(express.urlencoded({ extended: false })) // Allows us to handle url encoded data
  const middleware = require('../../../../src/middleware/middleware')
  app.use(middleware.createCtxAndReqUUID)
  
  const CONSTANTS = require('../../../../src/constants')
  const errors = require('../../../../src/controller/cve-id.controller/error')
  const error = new errors.CveIdControllerError()
  
  const cveIdNonSeqFixtures = require('./mockObjects.non-sequential')
  const cveIdControllerF = require('../../../../test-utils/reserveCaseF.non-sequential')
  const cveIdParams = require('../../../../src/controller/cve-id.controller/cve-id.middleware')
  
  class CveIdReservePoolIncremented10IdsCaseF {
    constructor () {
      this.docs = cveIdNonSeqFixtures.availableCveIdsF
    }
  
    getCveIdDocuments () {
      return this.docs
    }
  
    async insertMany (documents) {
      documents.forEach(doc => {
        this.docs.push(doc)
      })
      return documents
    }
  
    async countDocuments () {
      return 0
    }
  
    async find (query, options) {
      const res = []
      for (let i = 0; i < this.docs.length; i++) {
        if (this.docs[i].cve_year.toString() === query.cve_year && this.docs[i].state === query.state) {
          if (res.length < options.limit) {
            res.push(this.docs[i])
          }
        }
      }
  
      if (res.length === 0) {
        return []
      }
  
      return res
    }
  
    async findOneAndUpdate (query, updatedCveId) {
      let index = -1
      for (let i = 0; i < this.docs.length; i++) {
        if (this.docs[i].cve_id === query.cve_id && this.docs[i].state === query.state) {
          index = i
          break
        }
      }
  
      if (index >= 0) {
        this.docs[index] = updatedCveId
        return this.docs[index]
      }
  
      return null
    }
  }
  
  class CveIdRangeReserveNonSequentialCaseF {
    constructor () {
      this.year = '3000'
      this.cveIdRange = Object.assign({}, CONSTANTS.DEFAULT_CVE_ID_RANGE)
      this.cveIdRange.cve_year = this.year
      this.cveIdRange.ranges.general.top_id = 15
      this.cveIdRange.ranges.general.end = 20
    }
  
    getCveIdRange () {
      return this.cveIdRange
    }
  
    async findOne () {
      return this.cveIdRange
    }
  
    async findOneAndUpdate (query, set) {
      if (query.$and !== undefined) {
        if (query.$and[0].cve_year === this.year && query.$and[1]['ranges.general.end'] !== undefined &&
        this.cveIdRange.ranges.general.end >= query.$and[1]['ranges.general.end'].$gte) {
          this.cveIdRange.ranges.general.top_id += set.$inc['ranges.general.top_id']
          return this.cveIdRange
        } else if (query.$and[0].cve_year === this.year && set.$inc['ranges.general.top_id'] !== undefined) {
          this.cveIdRange.ranges.general.top_id = set.$set['ranges.general.top_id']
          return this.cveIdRange
        }
      } else if (query.cve_year === this.year) {
        this.cveIdRange.ranges.general.top_id = set.$set['ranges.general.top_id']
        return this.cveIdRange
      }
  
      return null
    }
  }
  
  const cveIdTestRepo = new CveIdReservePoolIncremented10IdsCaseF()
  const cveIdRangeTestRepo = new CveIdRangeReserveNonSequentialCaseF()
  
  describe('Testing the non sequential reservation (Case F) of POST /cve-id endpoint in CveId Controller', () => {
    context('Negative Tests', () => {
      it(`CveId Range document for year ${cveIdNonSeqFixtures.year} is full after race condition in pool increment`, (done) => {
        class UserReserveNonSequentialCaseF {
          async findOneByUserNameAndOrgUUID (username) {
            if (username === cveIdNonSeqFixtures.secretariatUser.username) {
              return cveIdNonSeqFixtures.secretariatUser
            }
  
            return cveIdNonSeqFixtures.userA
          }
        }
  
        class OrgReserveNonSequentialCaseF {
          async findOneByShortName () {
            return cveIdNonSeqFixtures.orgA
          }
  
          async getOrgUUID (shortname) {
            if (shortname === cveIdNonSeqFixtures.secretariatOrg.short_name) {
              return cveIdNonSeqFixtures.secretariatOrg.UUID
            }
  
            return cveIdNonSeqFixtures.orgA.UUID
          }
        }
  
        app.route('/cve-id-reserve-f-year-full-after-race-condition')
          .post((req, res, next) => {
            const factory = {
              getCveIdRepository: () => { return new CveIdReservePoolIncremented10IdsCaseF() },
              getCveIdRangeRepository: () => { return new CveIdRangeReserveNonSequentialCaseF() },
              getUserRepository: () => { return new UserReserveNonSequentialCaseF() },
              getOrgRepository: () => { return new OrgReserveNonSequentialCaseF() }
            }
            req.ctx.repositories = factory
            next()
          }, cveIdParams.parsePostParams, cveIdControllerF.CVEID_RESERVE)
  
        chai.request(app)
          .post(`/cve-id-reserve-f-year-full-after-race-condition?short_name=${cveIdNonSeqFixtures.orgA.short_name}&cve_year=${cveIdNonSeqFixtures.year}&amount=10&batch_type=non-sequential`)
          .set(cveIdNonSeqFixtures.userAHeader)
          .end((err, res) => {
            if (err) {
              done(err)
            }
  
            const quotaHeader = cveIdNonSeqFixtures.orgA.policies.id_quota.toString()
            expect(res.header).to.have.property('cve-api-remaining-quota').and.to.equal(quotaHeader)
  
            expect(res).to.have.status(403)
            expect(res).to.have.property('body').and.to.be.a('object')
            const errObj = error.yearRangeFull(cveIdNonSeqFixtures.year)
            expect(res.body.error).to.equal(errObj.error)
            expect(res.body.message).to.equal(errObj.message)
  
            // check total count of reserved ids by userA
            const docs = cveIdTestRepo.getCveIdDocuments()
            let reservedCounter = 0
            docs.forEach(doc => {
              if (doc.owning_cna === cveIdNonSeqFixtures.orgA.UUID && doc.cve_year === cveIdNonSeqFixtures.year && doc.state === 'RESERVED') {
                reservedCounter++
              }
            })
            expect(reservedCounter).to.equal(0)
  
            // check count of available ids
            let availableCounter = 0
            docs.forEach(doc => {
              if (doc.cve_year === cveIdNonSeqFixtures.year && doc.state === 'AVAILABLE') {
                availableCounter++
              }
            })
            expect(availableCounter).to.equal(0)
  
            // check that unreserved ids by userA are reserved
            const rangeDoc = cveIdRangeTestRepo.getCveIdRange()
            const topId = rangeDoc.ranges.general.top_id
            const reservedDocs = []
  
            for (let i = 0; i < docs.length; i++) {
              for (let j = 0; j < cveIdControllerF.reservedByOther.length; j++) {
                if (docs[i].cve_id === cveIdControllerF.reservedByOther[j] && docs[i].cve_year === cveIdNonSeqFixtures.year) {
                  reservedDocs.push(docs[i])
                  break
                }
              }
            }
            expect(reservedDocs).to.have.lengthOf(20)
            reservedDocs.forEach(obj => {
              const index = parseInt(obj.cve_id.match(/\d+$/g))
              expect(index).to.be.lessThan(topId + 1) // check that the id is less than the current top id
              expect(obj).to.have.property('state').and.to.equal('RESERVED')
              expect(obj).to.have.property('owning_cna').and.to.equal(cveIdNonSeqFixtures.secretariatOrg.UUID)
              expect(obj).to.have.nested.property('requested_by.cna').and.to.equal(cveIdNonSeqFixtures.secretariatUser.org_UUID)
              expect(obj).to.have.nested.property('requested_by.user').and.to.equal(cveIdNonSeqFixtures.secretariatUser.UUID)
            })
  
            done()
          })
      })
    })
  })
  