/* eslint-disable @typescript-eslint/no-non-null-assertion */ import { CUSTOMER_PATH, CreateCustomerRequest, CreateCustomerResponse, } from './api-types.js'; import {expect} from 'chai'; import {suite, test} from 'mocha'; import * as request from 'supertest'; import {prisma} from './db.js'; import {resetDB, newAppForTest, apiVersionTest} from './test-helpers.js'; const app = newAppForTest(); suite('Server: Customer', () => { suite('createCustomer', () => { const goodReq: CreateCustomerRequest = { name: 'name', project: 'project', email: 'foo@example.com', commercial: true, acceptedTOS: true, }; type ResponseMatcher = (response: CreateCustomerResponse) => void; const goodRespMatcher: ResponseMatcher = ( gotResponse: CreateCustomerResponse, ) => { expect(gotResponse.licenseKey).to.match(/^l[0-9A-F]+$/i); }; type TestCase = { desc: string; req: object; expStatus: number; expResponseMatcher: undefined | ResponseMatcher; expRecordCreated: boolean; }; const tests: TestCase[] = [ { desc: 'good request', req: goodReq, expStatus: 200, expResponseMatcher: goodRespMatcher, expRecordCreated: true, }, { desc: 'good request w/o project', req: {...goodReq, project: undefined}, expStatus: 200, expResponseMatcher: goodRespMatcher, expRecordCreated: true, }, { desc: 'bad: no name', req: {...goodReq, name: ' '}, expStatus: 400, expResponseMatcher: undefined, expRecordCreated: false, }, { desc: 'bad: no email', req: {...goodReq, email: ''}, expStatus: 400, expResponseMatcher: undefined, expRecordCreated: false, }, { desc: 'bad: did not accept ToS', req: {...goodReq, acceptedTOS: false}, expStatus: 400, expResponseMatcher: undefined, expRecordCreated: false, }, ]; tests.forEach(t => { test(t.desc, async () => { await resetDB(prisma); const response = await request .default(app) .post(CUSTOMER_PATH) .send(t.req) .set({ // eslint-disable-next-line @typescript-eslint/naming-convention 'Accept': 'appplication/json', // eslint-disable-next-line @typescript-eslint/naming-convention 'Content-Type': 'application/json', }); expect(response.statusCode).to.equal( t.expStatus, `${t.desc} expected status ${t.expStatus}, got status ${ response.statusCode }; request ${t.req.toString()}, response ${response.text}`, ); if (t.expResponseMatcher) { t.expResponseMatcher(response.body); } if (t.expRecordCreated) { expect(await prisma.customer.count()).to.equal(1); expect(await prisma.license.count()).to.equal(1); const license = await prisma.license.findUnique({ where: {key: response.body.licenseKey}, include: { customer: true, }, }); const r = t.req; expect(license).to.not.be.undefined; expect(license!.commercial).to.equal(r.commercial); expect(license!.acceptedTOS).to.equal(r.acceptedTOS); expect(license!.customer).to.not.be.undefined; expect(license!.customer!.name).to.equal(r.name); expect(license!.customer!.project).to.equal(r.project ?? null); // db stores null expect(license!.customer!.email).to.equal(r.email); } else { expect(await prisma.customer.count()).to.equal(0); expect(await prisma.license.count()).to.equal(0); } }).timeout(5000); }); test("Ensure it doesn't always issue the same license key", async () => { const response1 = await request .default(app) .post(CUSTOMER_PATH) .send(goodReq) .set({ // eslint-disable-next-line @typescript-eslint/naming-convention 'Accept': 'appplication/json', // eslint-disable-next-line @typescript-eslint/naming-convention 'Content-Type': 'application/json', }); expect(response1.statusCode).to.equal(200); const response2 = await request .default(app) .post(CUSTOMER_PATH) .send(goodReq) .set('Accept', 'appplication/json'); expect(response2.statusCode).to.equal(200); expect(response1.body.licenseKey).to.not.equal(response2.body.licenseKey); }); }); test('API version', async () => { const errText = 'Unsupported API version'; await apiVersionTest('2000.1', app, CUSTOMER_PATH, {}, 400, errText); await apiVersionTest('1.123124', app, CUSTOMER_PATH, {}, 400, errText); }); });