SylowTech/sylow

View on GitHub
tests/admin.test.js

Summary

Maintainability
F
1 wk
Test Coverage
import request from 'supertest-as-promised';
import cheerio from 'cheerio';
import httpStatus from 'http-status';
import chai, { expect } from 'chai';

import config from '../config/config';
import app from '../index';

import AccessToken from '../server/models/accessToken.model';
import Client from '../server/models/client.model';
import Entity from '../server/models/entity.model';
import Server from '../server/models/server.model';
import { randomStr } from '../server/utils/random';

chai.config.includeStack = true;

const adminSesh = request.agent(app);

const testEntity = {
  username: 'testuser',
  domain: 'sylow.dev',
  entityName: 'testuser@sylow.dev',
  passwordHash: '33f1ba50d3acdfe04fadbfcdc50edd84a3af0f9d377872003eaedbb68f8e6d7146e87c35e5f3338341d91b84c1371a6a9db054c4104797e99848f4d2d8a2b91e',
  passwordSalt: '694658b93aa9c2f245cca37da3b4d7cc',
  keypair: {
    public: 'xxxxx'
  },
  authoritative: true,
  admin: true
};

const testClient = {
  clientId: 'clientIdTest',
  clientName: 'clientNameTest',
  clientSecret: 'clientSecretTest',
  redirectUri: 'http://localhost/cb',
  deviceType: 'mobile'
};

const superfluousEntity = {
  username: 'newuser',
  domain: 'testDomain',
  passwordHash: 'xxxxxx',
  passwordSalt: 'xxxxxx',
  admin: true
};

const superfluousClient = {
  clientId: 'newclient',
  clientName: 'New Client',
  clientSecret: 'xxxxxx',
  redirectUri: 'http://localhost/cb',
  deviceType: 'other'
};

const testAccessToken = {
  token: randomStr(256)
};

const authoritativeServer = {
  domain: 'serverDomainTest',
  name: 'serverNameTest',
  description: 'serverDescriptionTest',
  keypair: {
    public: 'xxxxx',
    private: 'xxxxx'
  },
  authoritative: true
};

const superfluousServer = {
  domain: 'newServer',
  name: 'New Server',
  description: 'New Server\'s description',
  keypair: {
    public: 'xxxxx',
  }
};

describe('## Admin Interface', () => {
  before('Create and use test entity', () => {
    if (config.env !== 'test') {
      return Promise.reject('Not in a test environment');
    }
    return Promise.all([Entity.remove(), Client.remove(), AccessToken.remove()])
      .then(() => new Entity(testEntity).save())
      .then((entity) => {
        testEntity.id = entity._id;
        testAccessToken.entity = entity._id;
        return new Client(testClient).save();
      })
      .then((client) => {
        testClient.id = client._id;
        testAccessToken.client = client._id;
        return new AccessToken(testAccessToken).save();
      })
      .then((accessToken) => {
        testAccessToken.id = accessToken._id;
        return adminSesh.post('/login')
          .send({
            username: testEntity.username,
            passwordHash: testEntity.passwordHash
          })
          .type('form')
          .expect(httpStatus.FOUND)
          .then((res) => {
            expect(res.headers.location).to.equal('/');
          });
      });
  });

  describe('# GET /', () => {
    it('should return the dashboard page', (done) => {
      adminSesh.get('/')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const contents = html('.ui.sy-dashboard h1.ui.header').html();
          expect(contents).to.equal('Dashboard');
          expect(res.headers).to.have.property('sylow-serverid');
          expect(res.headers['sylow-serverid']).to.equal('testDomain');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /entities', () => {
    it('should return a list of entities', (done) => {
      adminSesh.get('/entities')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const contents = html('.ui.sy-dashboard .ui.four.cards');
          const testuserCard = contents.children().first();
          expect(contents.length).to.equal(1);
          expect(testuserCard.find('.content .header').first().html())
            .to.equal('testuser@sylow.dev');
          done();
        })
        .catch(done);
    });
  });

  describe('# POST /entities', () => {
    it('should fail to create an entity with missing information', (done) => {
      adminSesh.post('/entities')
        .redirects(1)
        .send({ username: 'xxxxxx', authoritative: true })
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const err = html('.ui.sy-dashboard .ui.error.message p').html();
          expect(err).to.equal('Missing values');
          done();
        })
        .catch(done);
    });

    it('should create an entity', (done) => {
      adminSesh.post('/entities')
        .redirects(1)
        .send(superfluousEntity)
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const contents = html('.ui.sy-dashboard .ui.four.cards').children();
          const testuserCard = contents.first();
          superfluousEntity.id = testuserCard.find('.ui.negative.button').data('params');
          expect(contents.length).to.equal(2);
          expect(testuserCard.find('.content .header').first().html())
            .to.equal('newuser@testDomain');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /entities/:id', () => {
    it('should show an entity', (done) => {
      adminSesh.get(`/entities/${testEntity.id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          expect(title).to.equal(`Entity: ${testEntity.entityName}`);
          done();
        })
        .catch(done);
    });
  });

  describe('# POST /entities/:id', () => {
    it('should update an entity', (done) => {
      adminSesh.post(`/entities/${testEntity.id}`)
        .redirects(1)
        .send({ username: 'newTest', admin: 1 })
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          expect(title).to.equal(`Entity: newTest@${testEntity.domain}`);
          return request(app).post('/login')
            .send({
              username: 'newTest',
              passwordHash: testEntity.passwordHash
            })
            .type('form')
            .expect(httpStatus.FOUND)
            .then((logRes) => {
              expect(logRes.headers.location).to.equal('/');
              done();
            });
        })
        .catch(done);
    });

    it('should update an entity with a new password', (done) => {
      adminSesh.post(`/entities/${testEntity.id}`)
        .redirects(1)
        .send({ username: 'testuser', admin: 1, passwordHash: 'xxxxxx', passwordSalt: 'xxxxxx' })
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          expect(title).to.equal(`Entity: testuser@${testEntity.domain}`);
          return request(app).post('/login')
            .send({
              username: 'testuser',
              passwordHash: 'xxxxxx'
            })
            .type('form')
            .expect(httpStatus.FOUND)
            .then((logRes) => {
              expect(logRes.headers.location).to.equal('/');
              done();
            });
        })
        .catch(done);
    });
  });

  describe('# DELETE /entities/:id', () => {
    it('should fail to delete a nonexistent entity', (done) => {
      adminSesh.delete('/entities/xxxxxx')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Entity does not exist');
          done();
        })
        .catch(done);
    });

    it('should delete an entity', (done) => {
      adminSesh.delete(`/entities/${superfluousEntity.id}`)
        .expect(httpStatus.NO_CONTENT)
        .then(() =>
          adminSesh.get('/entities')
            .expect(httpStatus.OK)
            .then((res) => {
              const html = cheerio.load(res.text);
              const contents = html('.ui.sy-dashboard .ui.four.cards');
              const testuserCard = contents.children().first();
              expect(contents.length).to.equal(1);
              expect(testuserCard.find('.content .header').first().html())
                .to.equal('testuser@sylow.dev');
              done();
            })
        )
        .catch(done);
    });
  });

  describe('# GET /clients', () => {
    it('should return a list of clients', (done) => {
      adminSesh.get('/clients')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const contents = html('.ui.sy-dashboard .ui.four.cards');
          const testuserCard = contents.children().first();
          expect(contents.length).to.equal(1);
          expect(testuserCard.find('.content .header').first().html())
            .to.equal('clientNameTest');
          done();
        })
        .catch(done);
    });
  });

  describe('# POST /clients', () => {
    it('should fail to create a client with missing information', (done) => {
      adminSesh.post('/clients')
        .redirects(1)
        .send({ clientId: 'xxxxxx', clientName: 'xxxxxx' })
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const err = html('.ui.sy-dashboard .ui.error.message p').html();
          expect(err).to.equal('Missing values');
          done();
        })
        .catch(done);
    });

    it('should create a client', (done) => {
      adminSesh.post('/clients')
        .redirects(1)
        .send(superfluousClient)
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const contents = html('.ui.sy-dashboard .ui.four.cards').children();
          const testuserCard = contents.first();
          superfluousClient.id = testuserCard.find('.ui.negative.button').data('params');
          expect(contents.length).to.equal(2);
          expect(testuserCard.find('.content .header').last().html())
            .to.equal('New Client');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /clients/:id', () => {
    it('should show a client', (done) => {
      adminSesh.get(`/clients/${testClient.id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          expect(title).to.equal(`Client: ${testClient.clientName}`);
          done();
        })
        .catch(done);
    });
  });

  describe('# POST /clients/:id', () => {
    it('should update a client', (done) => {
      testClient.clientName = 'newNameTest';
      adminSesh.post(`/clients/${testClient.id}`)
        .redirects(1)
        .send(testClient)
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          expect(title).to.equal(`Client: ${testClient.clientName}`);
          done();
        })
        .catch(done);
    });
  });

  describe('# DELETE /clients/:id', () => {
    it('should fail to delete a client', (done) => {
      adminSesh.delete('/clients/593576a8570f1de0f3303c87')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Client does not exist');
          done();
        })
        .catch(done);
    });

    it('should successfully delete a client', (done) => {
      adminSesh.delete(`/clients/${superfluousClient.id}`)
        .expect(httpStatus.NO_CONTENT)
        .then((res) => {
          expect(res.text).to.equal('');
          done();
        })
        .catch(done);
    });
  });

  describe('# DELETE /tokens/:id', () => {
    it('should fail to delete an access token', (done) => {
      adminSesh.delete('/tokens/593576a8570f1de0f3303c87')
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Tokens do not exist or client not associated');
          done();
        })
        .catch(done);
    });

    it('should successfully delete a token', (done) => {
      adminSesh.delete(`/tokens/${testAccessToken.id}`)
        .expect(httpStatus.NO_CONTENT)
        .then((res) => {
          expect(res.text).to.equal('');
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /settings', () => {
    it('should show the settings page', (done) => {
      adminSesh.get('/settings')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          const allowSignups = html('.allowSignups input').attr('value');
          expect(title).to.equal('Settings');
          expect(allowSignups).to.equal('on');
          done();
        })
        .catch(done);
    });
  });

  describe('# POST /settings', () => {
    it('should update settings', (done) => {
      const updSettings = {
        domain: 'testdomain.xyz',
        allowSignups: 'on',
        schemaDomainWhitelist: ['sylow.network']
      };
      adminSesh.post('/settings')
        .redirects(1)
        .send(updSettings)
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          const domainWhiteListInputs = html('.schemaDomainWhitelist input').get().length;
          expect(title).to.equal('Settings');
          expect(domainWhiteListInputs).to.equal(2);
          done();
        })
        .catch(done);
    });
  });

  describe('# GET /servers', () => {
    before('Create and use test servers', () => {
      if (config.env !== 'test') {
        return Promise.reject('Not in a test environment');
      }

      return Server.remove()
        .then(() => Server.create([authoritativeServer, superfluousServer]))
        .then(([newAuthServer, newExtraServer]) => {
          authoritativeServer.id = newAuthServer.id;
          superfluousServer.id = newExtraServer.id;
        });
    });

    it('should show the servers admin page', (done) => {
      adminSesh.get('/servers')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          const authoritativeServerDomain = html('tr.authoritative td').first().html();
          const simpleServerDomain = html('tr.non-authoritative td').html();
          expect(title).to.equal('Servers');
          expect(authoritativeServerDomain).to.equal('serverDomainTest');
          expect(simpleServerDomain).to.equal('newServer');
          done();
        })
        .catch(done);
    });

    it('should show the authoritative server\'s update form', (done) => {
      adminSesh.get(`/servers/${authoritativeServer.id}`)
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const title = html('.ui.sy-dashboard h1.ui.header').first().html();
          const name = html('form input[type="text"]').val();
          expect(title).to.equal(authoritativeServer.domain);
          expect(name).to.equal(authoritativeServer.name);
          done();
        })
        .catch(done);
    });
  });

  describe('# POST /servers/:id', () => {
    it('should update authoritative server', (done) => {
      authoritativeServer.name = 'newName';
      adminSesh.post(`/servers/${authoritativeServer.id}`)
        .redirects(1)
        .send(authoritativeServer)
        .type('form')
        .expect(httpStatus.OK)
        .then((res) => {
          const html = cheerio.load(res.text);
          const name = html('form input[type="text"]').val();
          expect(name).to.equal(authoritativeServer.name);
          done();
        })
        .catch(done);
    });
  });

  describe('# DELETE /servers/:id', () => {
    it('should fail to delete an authoritative server', (done) => {
      adminSesh.delete(`/servers/${authoritativeServer.id}`)
        .expect(httpStatus.NOT_FOUND)
        .then((res) => {
          expect(res.body.message).to.equal('Server does not exist');
          done();
        })
        .catch(done);
    });

    it('should successfully delete a non-authoritative server', (done) => {
      adminSesh.delete(`/servers/${superfluousServer.id}`)
        .expect(httpStatus.NO_CONTENT)
        .then((res) => {
          expect(res.text).to.equal('');
          done();
        })
        .catch(done);
    });
  });
});