Skip to content

Commit

Permalink
fix(api): Bugfixes resulting from testing Game.postStartCommand
Browse files Browse the repository at this point in the history
  • Loading branch information
jcowman2 committed Sep 5, 2018
1 parent f12ffb3 commit d02b7cc
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 8 deletions.
2 changes: 2 additions & 0 deletions src/config/game-options.ts
Expand Up @@ -24,3 +24,5 @@ export const DEFAULT_GAME_OPTIONS: GameOptions = {
forbidChanges: false,
showMinor: true
};

export const OPTION_KEYS = Object.keys(DEFAULT_GAME_OPTIONS);
2 changes: 1 addition & 1 deletion src/config/index.ts
@@ -1,3 +1,3 @@
export { InstanceOptions } from "./instance-options";
export { GameOptions, DEFAULT_GAME_OPTIONS } from "./game-options";
export { GameOptions, DEFAULT_GAME_OPTIONS, OPTION_KEYS } from "./game-options";
export { GameMetadata } from "./game-metadata";
11 changes: 6 additions & 5 deletions src/config/instance-options.ts
@@ -1,8 +1,6 @@
import { RegalError } from "../error";
import GameInstance from "../game-instance";
import { DEFAULT_GAME_OPTIONS, GameOptions } from "./game-options";

const OPTION_KEYS = Object.keys(DEFAULT_GAME_OPTIONS);
import { DEFAULT_GAME_OPTIONS, GameOptions, OPTION_KEYS } from "./game-options";

const OPTION_OVERRIDES_PROXY_HANDLER = {
set(
Expand Down Expand Up @@ -55,13 +53,16 @@ export class InstanceOptions implements GameOptions {
}

// Ensure that each overriden option has the correct type.
// TODO - this doesn't work well for nonprimitive options. Perhaps each one should be validated seperately.
if (typeof overrides[key] !== typeof DEFAULT_GAME_OPTIONS[key]) {
throw new RegalError(
`The option <${key}> is of type ${typeof overrides[
`The option <${key}> is of type <${typeof overrides[
key
]}, must be of type ${typeof DEFAULT_GAME_OPTIONS[key]}`
]}>, must be of type <${typeof DEFAULT_GAME_OPTIONS[key]}>.`
);
}

this[key] = overrides[key];
});

return new Proxy(this, INSTANCE_OPTIONS_PROXY_HANDLER);
Expand Down
2 changes: 1 addition & 1 deletion src/game-api.ts
Expand Up @@ -107,7 +107,7 @@ export class Game {
}

public static postStartCommand(
options: Partial<GameOptions>
options: Partial<GameOptions> = {}
): GameResponse {
let newInstance: GameInstance;
let err: RegalError;
Expand Down
120 changes: 119 additions & 1 deletion test/game-api.test.ts
Expand Up @@ -8,6 +8,7 @@ import GameInstance from "../src/game-instance";
import { OutputLineType } from "../src/output";
import { log } from "./utils";
import { Agent } from "../src/agents";
import { DEFAULT_GAME_OPTIONS, OPTION_KEYS, GameOptions } from "../src/config";

describe("Game API", function() {
beforeEach(function() {
Expand Down Expand Up @@ -176,7 +177,7 @@ describe("Game API", function() {
return noop;
});

const response = Game.postStartCommand({});
const response = Game.postStartCommand();

expect(response.instance).to.not.be.undefined;
expect(response.output).to.deep.equal({
Expand All @@ -190,5 +191,122 @@ describe("Game API", function() {
]
});
});

it("An error is thrown if the onStartCommand hook isn't set", function() {
const response = Game.postStartCommand();

expect(response.output.wasSuccessful).to.be.false;
expect(response.output.error.message).to.equal(
"RegalError: onStartCommand has not been implemented by the game developer."
);
expect(response.instance).to.be.undefined;
});

it("An error is thrown if the developer tries to throw an invalid error object", function() {
onStartCommand(() => {
throw 5;
});

const response = Game.postStartCommand();

expect(response.output.wasSuccessful).to.be.false;
expect(response.output.error.message).to.equal(
"RegalError: Invalid error object."
);
expect(response.instance).to.be.undefined;
});

it("A new RegalError is made if an error occurred during the game's runtime", function() {
onStartCommand(() => {
(<string[]>(<any>"lars")).push("blarp");
return noop;
});

const response = Game.postStartCommand();

expect(response.output.wasSuccessful).to.be.false;
expect(response.output.error.message).to.equal(
'RegalError: An error occurred while executing the request. Details: <TypeError: "lars".push is not a function>'
);
expect(response.instance).to.be.undefined;
});

it("Sending a no-arg start request uses the default option values", function() {
onStartCommand(game => noop);

const response = Game.postStartCommand();
const options = response.instance.options;

expect(options.overrides).to.deep.equal({});
OPTION_KEYS.forEach(key =>
expect(options[key]).to.equal(DEFAULT_GAME_OPTIONS[key])
);
});

it("Sending an empty start request uses the default option values", function() {
onStartCommand(game => noop);

const response = Game.postStartCommand({});
const options = response.instance.options;

expect(options.overrides).to.deep.equal({});
OPTION_KEYS.forEach(key =>
expect(options[key]).to.equal(DEFAULT_GAME_OPTIONS[key])
);
});

it("Sending a start request with options overrides the defaults", function() {
onStartCommand(game => noop);

const response = Game.postStartCommand({
debug: true
});
const options = response.instance.options;

expect(options.overrides).to.deep.equal({
debug: true
});
expect(options.debug).to.be.true;
expect(options.forbidChanges).to.equal(
DEFAULT_GAME_OPTIONS.forbidChanges
);
expect(options.showMinor).to.equal(DEFAULT_GAME_OPTIONS.showMinor);
});

it("Sending a start request with invalid options throws an error", function() {
onStartCommand(game => noop);

const response = Game.postStartCommand(<any>{ foo: 3 });

expect(response.output.wasSuccessful).to.be.false;
expect(response.output.error.message).to.equal(
"RegalError: Invalid option name <foo>."
);
expect(response.instance).to.be.undefined;
});

it("Sending a start requests with mistyped options throws an error (1)", function() {
onStartCommand(game => noop);

const response = Game.postStartCommand(<any>{ debug: 3 });

expect(response.output.wasSuccessful).to.be.false;
expect(response.output.error.message).to.equal(
"RegalError: The option <debug> is of type <number>, must be of type <boolean>."
);
expect(response.instance).to.be.undefined;
});

it("Sending a start requests with mistyped options throws an error (2)", function() {
onStartCommand(game => noop);

const response = Game.postStartCommand(<any>{ debug: [] });

expect(response.output.wasSuccessful).to.be.false;
expect(response.output.error.message).to.equal(
"RegalError: The option <debug> is of type <object>, must be of type <boolean>."
);
expect(response.instance).to.be.undefined;
});
});
});

0 comments on commit d02b7cc

Please sign in to comment.