<commit_before>const frisby = require('frisby')
var insecurity = require('../../lib/insecurity')

const API_URL = 'http://localhost:3000/api'
const REST_URL = 'http://localhost:3000/rest'

var authHeader = { 'Authorization': 'Bearer ' + insecurity.authorize() }

var validCoupon = insecurity.generateCoupon(new Date(), 15)
var outdatedCoupon = insecurity.generateCoupon(new Date(2001, 0, 1), 20)
var forgedCoupon = insecurity.generateCoupon(new Date(), 99)

describe('/rest/basket/:id', function () {
  it('GET existing basket by id is not allowed via public API', function (done) {
    frisby.get(REST_URL + '/basket/1')
      .expect('status', 401)
      .done(done)
  })

  it('GET empty basket when requesting non-existing basket id', function (done) {
    frisby.get(REST_URL + '/basket/4711', {headers: authHeader})
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', 'data', {})
      .done(done)
  })

  it('GET existing basket with contained products by id', function (done) {
    frisby.get(REST_URL + '/basket/1', {headers: authHeader})
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .then(function (res) {
        expect(res.json.data.id).toBe(1)
        expect(res.json.data.products.length).toBe(3)
      })
      .done(done)
  })
})

describe('/api/Baskets', function () {
  it('POST new basket is not part of API', function (done) {
    frisby.post(API_URL + '/Baskets', {
      headers: authHeader,
      body: {
        UserId: 1
      }
    })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.status).toBe('error')
      })
      .done(done)
  })

  it('GET all baskets is not part of API', function (done) {
    frisby.get(API_URL + '/Baskets', { headers: authHeader })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.status).toBe('error')
      })
      .done(done)
  })
})

describe('/api/Baskets/:id', function () {
  it('GET existing basket is not part of API', function (done) {
    frisby.get(API_URL + '/Baskets/1', { headers: authHeader })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.status).toBe('error')
      })
      .done(done)
  })

  it('PUT update existing basket is not part of API', function (done) {
    frisby.put(API_URL + '/Baskets/1', {
      headers: authHeader,
      body: { UserId: 2 }
    })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.status).toBe('error')
      })
      .done(done)
  })

  it('DELETE existing basket is not part of API', function (done) {
    frisby.del(API_URL + '/Baskets/1', { headers: authHeader })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.status).toBe('error')
      })
      .done(done)
  })
})

describe('/rest/basket/:id/checkout', function () {
  it('POST placing an order for a basket is not allowed via public API', function (done) {
    frisby.post(REST_URL + '/basket/1/checkout')
      .expect('status', 401)
      .done(done)
  })

  it('POST placing an order for an existing basket returns path to an order confirmation PDF', function (done) {
    frisby.post(REST_URL + '/basket/1/checkout', { headers: authHeader })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.orderConfirmation).toMatch(/\/ftp\/order_.*\.pdf/)
      })
      .done(done)
  })

  it('POST placing an order for a non-existing basket fails', function (done) {
    frisby.post(REST_URL + '/basket/42/checkout', { headers: authHeader })
      .expect('status', 500)
      .expect('bodyContains', 'Error: Basket with id=42 does not exist.')
      .done(done)
  })

  it('POST placing an order for a basket with a negative total cost is possible', function (done) {
    // FIXME Adds a basket item with both IDs and quantity as <null> to Basket #3
    frisby.post(API_URL + '/BasketItems', {
      headers: authHeader,
      body: { BasketId: 3, ProductId: 10, quantity: -100 }
    })
      .expect('status', 200)
      .then(function () {
        return frisby.post(REST_URL + '/basket/3/checkout', { headers: authHeader })
          .expect('status', 200)
          .then(function (res) {
            expect(res.json.orderConfirmation).toMatch(/\/ftp\/order_.*\.pdf/)
          })
      })
      .done(done)
  })

  it('POST placing an order for a basket with 99% discount is possible', function (done) {
    frisby.put(REST_URL + '/basket/2/coupon/' + encodeURIComponent(forgedCoupon), { headers: authHeader })
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', {discount: 99})
      .then(function () {
        return frisby.post(REST_URL + '/basket/2/checkout', { headers: authHeader })
          .expect('status', 200)
          .then(function (res) {
            expect(res.json.orderConfirmation).toMatch(/\/ftp\/order_.*\.pdf/)
          })
      })
      .done(done)
  })
})

describe('/rest/basket/:id/coupon/:coupon', function () {
  it('PUT apply valid coupon to existing basket', function (done) {
    frisby.put(REST_URL + '/basket/1/coupon/' + encodeURIComponent(validCoupon), { headers: authHeader })
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', {discount: 15})
      .done(done)
  })

  xit('PUT apply invalid coupon is not accepted', function (done) {
    frisby.put(REST_URL + '/basket/1/coupon/xxxxxxxxxx', { headers: authHeader })
      .expect('status', 404)
      .done(done)
  })

  it('PUT apply outdated coupon is not accepted', function (done) {
    frisby.put(REST_URL + '/basket/1/coupon/' + encodeURIComponent(outdatedCoupon), { headers: authHeader })
      .expect('status', 404)
      .done(done)
  })

  it('PUT apply valid coupon to non-existing basket throws error', function (done) {
    frisby.put(REST_URL + '/basket/4711/coupon/' + encodeURIComponent(validCoupon), { headers: authHeader })
      .expect('status', 500)
      .done(done)
  })
})
<commit_msg>Adapt to JSON non-strict expectations (see https://github.com/vlucas/frisby/issues/365)<commit_after>const frisby = require('frisby')
var insecurity = require('../../lib/insecurity')

const API_URL = 'http://localhost:3000/api'
const REST_URL = 'http://localhost:3000/rest'

var authHeader = { 'Authorization': 'Bearer ' + insecurity.authorize() }

var validCoupon = insecurity.generateCoupon(new Date(), 15)
var outdatedCoupon = insecurity.generateCoupon(new Date(2001, 0, 1), 20)
var forgedCoupon = insecurity.generateCoupon(new Date(), 99)

describe('/rest/basket/:id', function () {
  it('GET existing basket by id is not allowed via public API', function (done) {
    frisby.get(REST_URL + '/basket/1')
      .expect('status', 401)
      .done(done)
  })

  it('GET empty basket when requesting non-existing basket id', function (done) {
    frisby.get(REST_URL + '/basket/4711', {headers: authHeader})
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', 'data', {})
      .done(done)
  })

  it('GET existing basket with contained products by id', function (done) {
    frisby.get(REST_URL + '/basket/1', {headers: authHeader})
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', 'data', {id: 1})
      .then(function (res) {
        expect(res.json.data.products.length).toBe(3)
      })
      .done(done)
  })
})

describe('/api/Baskets', function () {
  it('POST new basket is not part of API', function (done) {
    frisby.post(API_URL + '/Baskets', {
      headers: authHeader,
      body: {
        UserId: 1
      }
    })
      .expect('status', 200)
      .expect('json', { status: 'error' })
      .done(done)
  })

  it('GET all baskets is not part of API', function (done) {
    frisby.get(API_URL + '/Baskets', { headers: authHeader })
      .expect('status', 200)
      .expect('json', { status: 'error' })
      .done(done)
  })
})

describe('/api/Baskets/:id', function () {
  it('GET existing basket is not part of API', function (done) {
    frisby.get(API_URL + '/Baskets/1', { headers: authHeader })
      .expect('status', 200)
      .expect('json', { status: 'error' })
      .done(done)
  })

  it('PUT update existing basket is not part of API', function (done) {
    frisby.put(API_URL + '/Baskets/1', {
      headers: authHeader,
      body: { UserId: 2 }
    })
      .expect('status', 200)
      .expect('json', { status: 'error' })
      .done(done)
  })

  it('DELETE existing basket is not part of API', function (done) {
    frisby.del(API_URL + '/Baskets/1', { headers: authHeader })
      .expect('status', 200)
      .expect('json', { status: 'error' })
      .done(done)
  })
})

describe('/rest/basket/:id/checkout', function () {
  it('POST placing an order for a basket is not allowed via public API', function (done) {
    frisby.post(REST_URL + '/basket/1/checkout')
      .expect('status', 401)
      .done(done)
  })

  it('POST placing an order for an existing basket returns path to an order confirmation PDF', function (done) {
    frisby.post(REST_URL + '/basket/1/checkout', { headers: authHeader })
      .expect('status', 200)
      .then(function (res) {
        expect(res.json.orderConfirmation).toMatch(/\/ftp\/order_.*\.pdf/)
      })
      .done(done)
  })

  it('POST placing an order for a non-existing basket fails', function (done) {
    frisby.post(REST_URL + '/basket/42/checkout', { headers: authHeader })
      .expect('status', 500)
      .expect('bodyContains', 'Error: Basket with id=42 does not exist.')
      .done(done)
  })

  it('POST placing an order for a basket with a negative total cost is possible', function (done) {
    // FIXME Adds a basket item with both IDs and quantity as <null> to Basket #3
    frisby.post(API_URL + '/BasketItems', {
      headers: authHeader,
      body: { BasketId: 3, ProductId: 10, quantity: -100 }
    })
      .expect('status', 200)
      .then(function () {
        return frisby.post(REST_URL + '/basket/3/checkout', { headers: authHeader })
          .expect('status', 200)
          .then(function (res) {
            expect(res.json.orderConfirmation).toMatch(/\/ftp\/order_.*\.pdf/)
          })
      })
      .done(done)
  })

  it('POST placing an order for a basket with 99% discount is possible', function (done) {
    frisby.put(REST_URL + '/basket/2/coupon/' + encodeURIComponent(forgedCoupon), { headers: authHeader })
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', {discount: 99})
      .then(function () {
        return frisby.post(REST_URL + '/basket/2/checkout', { headers: authHeader })
          .expect('status', 200)
          .then(function (res) {
            expect(res.json.orderConfirmation).toMatch(/\/ftp\/order_.*\.pdf/)
          })
      })
      .done(done)
  })
})

describe('/rest/basket/:id/coupon/:coupon', function () {
  it('PUT apply valid coupon to existing basket', function (done) {
    frisby.put(REST_URL + '/basket/1/coupon/' + encodeURIComponent(validCoupon), { headers: authHeader })
      .expect('status', 200)
      .expect('header', 'content-type', /application\/json/)
      .expect('json', {discount: 15})
      .done(done)
  })

  xit('PUT apply invalid coupon is not accepted', function (done) {
    frisby.put(REST_URL + '/basket/1/coupon/xxxxxxxxxx', { headers: authHeader })
      .expect('status', 404)
      .done(done)
  })

  it('PUT apply outdated coupon is not accepted', function (done) {
    frisby.put(REST_URL + '/basket/1/coupon/' + encodeURIComponent(outdatedCoupon), { headers: authHeader })
      .expect('status', 404)
      .done(done)
  })

  it('PUT apply valid coupon to non-existing basket throws error', function (done) {
    frisby.put(REST_URL + '/basket/4711/coupon/' + encodeURIComponent(validCoupon), { headers: authHeader })
      .expect('status', 500)
      .done(done)
  })
})

{'fraction_non_alphanumeric': 0.1673432192858918, 'fraction_numerical': 0.019965205865296994, 'mean_word_length': 2.871712636305324, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 2, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5906798', 'n_tokens_mistral': 4189, 'n_tokens_neox': 3942, 'n_words': 925}