Add Postgraphile subscription exposure

- Add automation for TypeScript project build and tests via
  Webpack, tsc, and Jasmine
- Add custom Express application to serve Postgraphile
  subscription endpoints
- Add automated test suite for subscription endpoints
This commit is contained in:
James Christie
2018-09-04 20:20:43 -05:00
parent 1916d585fa
commit ed5b6c8f14
22 changed files with 5113 additions and 0 deletions
+104
View File
@@ -0,0 +1,104 @@
import { PassportStatic } from 'passport';
import { PostgraphileMiddleware } from '../../src/adapters/postgraphile';
import { buildServerConfig } from '../../src/server/config';
import {
DatabaseConfig,
ServerConfig,
ServerUtilities
} from '../../src/server/interface';
describe('buildServerConfig', () => {
let configParser: jasmine.Spy;
let postgraphileMiddleware: PostgraphileMiddleware;
let expressSessionHandler: jasmine.Spy;
let passportInitializer: jasmine.Spy;
let passportSessionHandler: jasmine.Spy;
let serverConfig: ServerConfig;
let serverUtilities: ServerUtilities;
let databaseConfig: DatabaseConfig;
beforeEach(() => {
databaseConfig = { host: 'example.com', database: 'example_database' };
postgraphileMiddleware = jasmine
.createSpyObj<PostgraphileMiddleware>(['call']),
serverUtilities = {
enableSubscriptions: jasmine.createSpy('enableSubscriptions'),
express: jasmine.createSpy('express'),
expressSession: jasmine.createSpy('expressSession'),
httpServerFactory: jasmine.createSpy('httpServerFactory'),
passport: jasmine.createSpyObj<PassportStatic>(['initialize', 'session']),
postgraphile: jasmine.createSpy('postgraphile')
};
const rawConfig: object = { exampleOption: 'example value' };
configParser = jasmine.createSpy('configParser');
configParser.and.returnValue(rawConfig);
expressSessionHandler = jasmine.createSpy('expressSessionHandler');
passportInitializer = jasmine.createSpy('passportInitializer');
passportSessionHandler = jasmine.createSpy('passportSessionHandler');
(serverUtilities.postgraphile as jasmine.Spy)
.and.returnValue(postgraphileMiddleware);
(serverUtilities.expressSession as jasmine.Spy)
.and.returnValue(expressSessionHandler);
(serverUtilities.passport.initialize as jasmine.Spy)
.and.returnValue(passportInitializer);
(serverUtilities.passport.session as jasmine.Spy)
.and.returnValue(passportSessionHandler);
serverConfig = buildServerConfig(
serverUtilities, databaseConfig, undefined);
});
it('provides the Postgraphile options', () => {
expect(serverConfig.options).not.toBeNull();
});
it('enables simple subscriptions', () => {
expect(serverConfig.options.simpleSubscriptions).toBe(true);
});
it('it adds the express session handler as the first middleware', () => {
expect(serverConfig.options.webSocketMiddlewares[0])
.toBe(expressSessionHandler);
});
it('it adds the passport initializer as the second middleware', () => {
expect(serverConfig.options.webSocketMiddlewares[1])
.toBe(passportInitializer);
});
it('it adds the passport session handler as the third middleware', () => {
expect(serverConfig.options.webSocketMiddlewares[2])
.toBe(passportSessionHandler);
});
it('provides the database config to Postgraphile', () => {
expect(serverUtilities.postgraphile).toHaveBeenCalledWith(
databaseConfig.host,
databaseConfig.database,
jasmine.any(Object));
});
it('provides the Postgraphile middleware', () => {
expect(serverConfig.middleware).toBe(postgraphileMiddleware);
});
it('sets the default server port', () => {
expect(serverConfig.port).toEqual(3000);
});
it('sets an explicit server port', () => {
const serverConfigWithPort = buildServerConfig(
serverUtilities, databaseConfig, '1234');
expect(serverConfigWithPort.port).toEqual(1234);
});
});
+64
View File
@@ -0,0 +1,64 @@
import { Express } from 'express';
import { PassportStatic } from 'passport';
import { Server } from 'http';
import { ServerUtilities, ServerConfig } from '../../src/server/interface';
import { bootServer } from '../../src/server/runtime';
import { PostgraphileMiddleware } from '../../src/adapters/postgraphile';
describe('bootServer', () => {
let serverUtilities: ServerUtilities;
let serverConfig: ServerConfig;
let mockExpressApp: Express;
let mockHttpServer: Server;
beforeEach(() => {
serverUtilities = {
enableSubscriptions: jasmine.createSpy('enableSubscriptions'),
express: jasmine.createSpy('express'),
expressSession: jasmine.createSpy('expressSession'),
httpServerFactory: jasmine.createSpy('httpServerFactory'),
passport: jasmine.createSpyObj<PassportStatic>(['initialize', 'session']),
postgraphile: jasmine.createSpy('postgraphile')
};
serverConfig = {
middleware: jasmine.createSpyObj<PostgraphileMiddleware>(['call']),
options: { simpleSubscriptions: true, webSocketMiddlewares: [] },
port: 5678
};
mockExpressApp = jasmine.createSpyObj<Express>(['use']);
(serverUtilities.express as jasmine.Spy)
.and.returnValue(mockExpressApp);
mockHttpServer = jasmine.createSpyObj<Server>(['listen']);
(serverUtilities.httpServerFactory as jasmine.Spy)
.and.returnValue(mockHttpServer);
bootServer(serverUtilities, serverConfig);
});
it('builds a new, Node HTTP server', () => {
expect(serverUtilities.httpServerFactory)
.toHaveBeenCalledWith(mockExpressApp);
});
it('provides Postgraphile middleware to the Express app', () => {
const useSpy = mockExpressApp.use as jasmine.Spy;
expect(useSpy).toHaveBeenCalledWith(serverConfig.middleware);
});
it('enahances the Node HTTP server with Postgraphile subscriptions', () => {
expect(serverUtilities.enableSubscriptions)
.toHaveBeenCalledWith(
mockHttpServer,
serverConfig.middleware,
serverConfig.options);
});
it('instructs the server to listen on the given port', () => {
const listenSpy = mockHttpServer.listen as jasmine.Spy;
expect(listenSpy).toHaveBeenCalledWith(serverConfig.port);
});
});