diff --git a/src/LabyrinthMiddleware.spec.ts b/src/LabyrinthMiddleware.spec.ts new file mode 100644 index 0000000..4561679 --- /dev/null +++ b/src/LabyrinthMiddleware.spec.ts @@ -0,0 +1,66 @@ +// to get rid of "[ts] could not find module ..." in vs code realod the window: f1 -> type "reload window" +// official issue for this: https://github.com/Microsoft/TypeScript/issues/10346 + +import {expect} from "chai"; +import * as express from "express"; +import { buildSchema } from "graphql"; +import { GameServer } from "./GameServer"; +import { CreateLabyrinthMiddleware, schemaDefinition } from "./LabyrinthMiddleware"; +import { createSampleMaps } from "./SampleMaps"; +// import { describe, it } from "mocha"; + +describe("Scenario: building the GraphQL schema", function(){ + it("should not break", function(){ + const notBreakingFunction = () => { buildSchema(schemaDefinition); }; + expect(notBreakingFunction).to.not.throw; + }); +}); + +describe("Scenario: Creating middleware.", function(){ + describe("Given the sample maps", function(){ + const games = new GameServer(); + const maps = createSampleMaps(); + maps.forEach(m => games.addMap(m)); + + describe("When the middleware is created with graphiql", function(){ + const graphiql = true; + const notBreakingFunction = () => { CreateLabyrinthMiddleware(graphiql, games); }; + it("then it should not break", function(){ + expect(notBreakingFunction).to.not.throw; + }); + }); + + describe("When the middleware is created without graphiql", function(){ + const graphiql = false; + const notBreakingFunction = () => { CreateLabyrinthMiddleware(graphiql, games); }; + it("then it should not break", function(){ + expect(notBreakingFunction).to.not.throw; + }); + }); + }); +}); + +describe("Scenario: Starting an express server", function(){ + describe("Given the sample maps, an express server and labyrinth middleware", function(){ + const games = new GameServer(); + const maps = createSampleMaps(); + maps.forEach(m => games.addMap(m)); + + const app = express(); + + const middleware = CreateLabyrinthMiddleware(false, games); + + app.use("/", middleware); + + describe("When the server is started", function(){ + it("then it should not break", function(done:Mocha.Done){ + // not sure, if this is such a good construct + const notBreakingFunction = () => { + const server = app.listen(8081, () => { server.close(); }); + }; + expect(notBreakingFunction).to.not.throw; + done(); + }); + }); + }); +}); diff --git a/src/LabyrinthMiddleware.spec.ts b/src/LabyrinthMiddleware.spec.ts new file mode 100644 index 0000000..4561679 --- /dev/null +++ b/src/LabyrinthMiddleware.spec.ts @@ -0,0 +1,66 @@ +// to get rid of "[ts] could not find module ..." in vs code realod the window: f1 -> type "reload window" +// official issue for this: https://github.com/Microsoft/TypeScript/issues/10346 + +import {expect} from "chai"; +import * as express from "express"; +import { buildSchema } from "graphql"; +import { GameServer } from "./GameServer"; +import { CreateLabyrinthMiddleware, schemaDefinition } from "./LabyrinthMiddleware"; +import { createSampleMaps } from "./SampleMaps"; +// import { describe, it } from "mocha"; + +describe("Scenario: building the GraphQL schema", function(){ + it("should not break", function(){ + const notBreakingFunction = () => { buildSchema(schemaDefinition); }; + expect(notBreakingFunction).to.not.throw; + }); +}); + +describe("Scenario: Creating middleware.", function(){ + describe("Given the sample maps", function(){ + const games = new GameServer(); + const maps = createSampleMaps(); + maps.forEach(m => games.addMap(m)); + + describe("When the middleware is created with graphiql", function(){ + const graphiql = true; + const notBreakingFunction = () => { CreateLabyrinthMiddleware(graphiql, games); }; + it("then it should not break", function(){ + expect(notBreakingFunction).to.not.throw; + }); + }); + + describe("When the middleware is created without graphiql", function(){ + const graphiql = false; + const notBreakingFunction = () => { CreateLabyrinthMiddleware(graphiql, games); }; + it("then it should not break", function(){ + expect(notBreakingFunction).to.not.throw; + }); + }); + }); +}); + +describe("Scenario: Starting an express server", function(){ + describe("Given the sample maps, an express server and labyrinth middleware", function(){ + const games = new GameServer(); + const maps = createSampleMaps(); + maps.forEach(m => games.addMap(m)); + + const app = express(); + + const middleware = CreateLabyrinthMiddleware(false, games); + + app.use("/", middleware); + + describe("When the server is started", function(){ + it("then it should not break", function(done:Mocha.Done){ + // not sure, if this is such a good construct + const notBreakingFunction = () => { + const server = app.listen(8081, () => { server.close(); }); + }; + expect(notBreakingFunction).to.not.throw; + done(); + }); + }); + }); +}); diff --git a/src/LabyrinthMiddleware.ts b/src/LabyrinthMiddleware.ts new file mode 100644 index 0000000..fb7b857 --- /dev/null +++ b/src/LabyrinthMiddleware.ts @@ -0,0 +1,80 @@ +import * as graphqlHTTP from "express-graphql"; +import {buildSchema} from "graphql"; +import { GameServer } from "./GameServer"; +import { Direction, MazeTile } from "./MazeMap"; + +export const schemaDefinition = ` + enum Direction { + none + top + left + bottom + right + } + + """ + Representing a tile with it's possible pathways. + """ + type MazeTileQL { + id: String! + paths: [Direction!]! + } + + type Mutation { + "Start a new game" + startGame(userID: String!, mapID: String!): MazeTileQL + } + + type Query { + "Tells you your where you currently are and how it looks there in case you forgot." + currentPostition(userID: String!): MazeTileQL + + "Lists currently available maps." + listMaps: [String!]! + } +`; + +class MazeTileQL +{ + public static DirectionToString(dir:Direction): string + { + switch (dir) { + case Direction.none: return "none"; + case Direction.top: return "top"; + case Direction.left: return "left"; + case Direction.bottom: return "bottom"; + case Direction.right: return "right"; + } + } + + public id:string; + public paths:string[]; + + constructor(tile:MazeTile) + { + this.id = tile.id; + this.paths = tile.paths.map(MazeTileQL.DirectionToString); + } +} + +function createGraphQLRoot(games:GameServer) +{ + return { + currentPostition: ({userID}) => new MazeTileQL(games.currentPosition(userID)), + listMaps: () => games.listMaps(), + startGame: ({userID, mapID}) => new MazeTileQL(games.startGame(userID, mapID)), + }; +} + +export function CreateLabyrinthMiddleware(graphiql:boolean, games:GameServer): graphqlHTTP.Middleware +{ + const schema = buildSchema(schemaDefinition); + + const root = createGraphQLRoot(games); + + return graphqlHTTP({ + graphiql: true, + rootValue: root, + schema, + }); +} diff --git a/src/LabyrinthMiddleware.spec.ts b/src/LabyrinthMiddleware.spec.ts new file mode 100644 index 0000000..4561679 --- /dev/null +++ b/src/LabyrinthMiddleware.spec.ts @@ -0,0 +1,66 @@ +// to get rid of "[ts] could not find module ..." in vs code realod the window: f1 -> type "reload window" +// official issue for this: https://github.com/Microsoft/TypeScript/issues/10346 + +import {expect} from "chai"; +import * as express from "express"; +import { buildSchema } from "graphql"; +import { GameServer } from "./GameServer"; +import { CreateLabyrinthMiddleware, schemaDefinition } from "./LabyrinthMiddleware"; +import { createSampleMaps } from "./SampleMaps"; +// import { describe, it } from "mocha"; + +describe("Scenario: building the GraphQL schema", function(){ + it("should not break", function(){ + const notBreakingFunction = () => { buildSchema(schemaDefinition); }; + expect(notBreakingFunction).to.not.throw; + }); +}); + +describe("Scenario: Creating middleware.", function(){ + describe("Given the sample maps", function(){ + const games = new GameServer(); + const maps = createSampleMaps(); + maps.forEach(m => games.addMap(m)); + + describe("When the middleware is created with graphiql", function(){ + const graphiql = true; + const notBreakingFunction = () => { CreateLabyrinthMiddleware(graphiql, games); }; + it("then it should not break", function(){ + expect(notBreakingFunction).to.not.throw; + }); + }); + + describe("When the middleware is created without graphiql", function(){ + const graphiql = false; + const notBreakingFunction = () => { CreateLabyrinthMiddleware(graphiql, games); }; + it("then it should not break", function(){ + expect(notBreakingFunction).to.not.throw; + }); + }); + }); +}); + +describe("Scenario: Starting an express server", function(){ + describe("Given the sample maps, an express server and labyrinth middleware", function(){ + const games = new GameServer(); + const maps = createSampleMaps(); + maps.forEach(m => games.addMap(m)); + + const app = express(); + + const middleware = CreateLabyrinthMiddleware(false, games); + + app.use("/", middleware); + + describe("When the server is started", function(){ + it("then it should not break", function(done:Mocha.Done){ + // not sure, if this is such a good construct + const notBreakingFunction = () => { + const server = app.listen(8081, () => { server.close(); }); + }; + expect(notBreakingFunction).to.not.throw; + done(); + }); + }); + }); +}); diff --git a/src/LabyrinthMiddleware.ts b/src/LabyrinthMiddleware.ts new file mode 100644 index 0000000..fb7b857 --- /dev/null +++ b/src/LabyrinthMiddleware.ts @@ -0,0 +1,80 @@ +import * as graphqlHTTP from "express-graphql"; +import {buildSchema} from "graphql"; +import { GameServer } from "./GameServer"; +import { Direction, MazeTile } from "./MazeMap"; + +export const schemaDefinition = ` + enum Direction { + none + top + left + bottom + right + } + + """ + Representing a tile with it's possible pathways. + """ + type MazeTileQL { + id: String! + paths: [Direction!]! + } + + type Mutation { + "Start a new game" + startGame(userID: String!, mapID: String!): MazeTileQL + } + + type Query { + "Tells you your where you currently are and how it looks there in case you forgot." + currentPostition(userID: String!): MazeTileQL + + "Lists currently available maps." + listMaps: [String!]! + } +`; + +class MazeTileQL +{ + public static DirectionToString(dir:Direction): string + { + switch (dir) { + case Direction.none: return "none"; + case Direction.top: return "top"; + case Direction.left: return "left"; + case Direction.bottom: return "bottom"; + case Direction.right: return "right"; + } + } + + public id:string; + public paths:string[]; + + constructor(tile:MazeTile) + { + this.id = tile.id; + this.paths = tile.paths.map(MazeTileQL.DirectionToString); + } +} + +function createGraphQLRoot(games:GameServer) +{ + return { + currentPostition: ({userID}) => new MazeTileQL(games.currentPosition(userID)), + listMaps: () => games.listMaps(), + startGame: ({userID, mapID}) => new MazeTileQL(games.startGame(userID, mapID)), + }; +} + +export function CreateLabyrinthMiddleware(graphiql:boolean, games:GameServer): graphqlHTTP.Middleware +{ + const schema = buildSchema(schemaDefinition); + + const root = createGraphQLRoot(games); + + return graphqlHTTP({ + graphiql: true, + rootValue: root, + schema, + }); +} diff --git a/src/app.ts b/src/app.ts index caf772f..a095451 100644 --- a/src/app.ts +++ b/src/app.ts @@ -1,82 +1,16 @@ import * as express from "express"; -import * as graphqlHTTP from "express-graphql"; -import {buildSchema} from "graphql"; import { GameServer } from "./GameServer"; -import { Direction, MazeTile } from "./MazeMap"; +import { CreateLabyrinthMiddleware } from "./LabyrinthMiddleware"; import { createSampleMaps } from "./SampleMaps"; const port = 8080; const apiRoot = "/graphql"; const app = express(); -const schema = buildSchema(` - enum Direction { - none - top - left - bottom - right - } - - """ - Representing a tile with it's possible pathways. - """ - type MazeTileQL { - id: String! - paths: [Direction!]! - } - - type Mutation { - "Start a new game" - startGame(userID: String!, mapID: String!): MazeTileQL - } - - type Query { - "Tells you your where you currently are and how it looks there in case you forgot." - currentPostition(userID: String!): MazeTileQL - - "Lists currently available maps." - listMaps: [String!]! - } -`); - -class MazeTileQL -{ - public static DirectionToString(dir:Direction): string - { - switch (dir) { - case Direction.none: return "none"; - case Direction.top: return "top"; - case Direction.left: return "left"; - case Direction.bottom: return "bottom"; - case Direction.right: return "right"; - } - } - - public id:string; - public paths:string[]; - - constructor(tile:MazeTile) - { - this.id = tile.id; - this.paths = tile.paths.map(MazeTileQL.DirectionToString); - } -} - const games = new GameServer(); const maps = createSampleMaps(); maps.forEach(m => games.addMap(m)); -const root = { - currentPostition: ({userID}) => new MazeTileQL(games.currentPosition(userID)), - listMaps: () => games.listMaps(), - startGame: ({userID, mapID}) => new MazeTileQL(games.startGame(userID, mapID)), -}; - -app.use(apiRoot, graphqlHTTP({ - graphiql: true, - rootValue: root, - schema, -})); +app.use(apiRoot, CreateLabyrinthMiddleware(true, games)); app.listen(port, () => console.log(`App listening on port ${port}...`));