Last active
May 25, 2018 14:02
-
-
Save JoshuaKGoldberg/f1c8e4dbc0c02cbdafa437ebe20289e3 to your computer and use it in GitHub Desktop.
π Unit Tests: SOLID, Modern, Electric Boogaloo π
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const createRouteDetails = (lookupId?: string): IRouteDetails => { | |
if (lookupId === undefined) { | |
return { | |
pageMode: PageMode.MySways, | |
}; | |
} | |
return { | |
lookupId, | |
pageMode: PageMode.Document, | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("DialogManager", () => { | |
describe("showMessage", () => { | |
it("sets the current dialog message", () => { | |
// Arrange | |
const manager = new DialogManager("", new Map()); | |
const message = "foo"; | |
// Act | |
manager.showMessage(message); | |
// Assert | |
expect(manager.getDialog()).toEqual(message); | |
}); | |
it("uses the default message when no message is provided", () => { | |
// Arrange | |
const defaultMessage = "foo"; | |
const manager = new DialogManager(defaultMessage, new Map()); | |
// Act | |
manager.showMessage(undefined); | |
// Assert | |
expect(manager.getDialog()).toEqual(defaultMessage); | |
}); | |
it("uses a message alias when the message matches an alias", () => { | |
// Arrange | |
const alias: [string, string] = ["foo", "bar"]; | |
const manager = new DialogManager("", new Map([alias])); | |
// Act | |
manager.showMessage(alias[0]); | |
// Assert | |
expect(manager.getDialog()).toEqual(alias[1]); | |
}); | |
it("uses the message when it's provided and doesn't match any alias", () => { | |
// Arrange | |
const manager = new DialogManager("", new Map()); | |
const message = "foo"; | |
// Act | |
manager.showMessage(message); | |
// Assert | |
expect(manager.getDialog()).toEqual(message); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DialogManager { | |
private currentDialog?: string; | |
private readonly defaultMessage: string; | |
private readonly messageAliases: Map<string, string> | |
public constructor(defaultMessage: string, messageAliases: Map<string, string>) { | |
this.defaultMessage = defaultMessage; | |
this.messageAliases = messageAliases; | |
} | |
public getDialog(): string | undefined { | |
return this.currentDialog; | |
} | |
public showMessage(message: string | undefined): void { | |
this.currentDialog = this.createDialogMessage(message); | |
} | |
private createDialogMessage(message: string | undefined): string { | |
if (message === undefined) { | |
return this.defaultMessage; | |
} | |
const messageAlias = this.messageAliases.get(message); | |
return messageAlias === undefined | |
? messageAlias | |
: message; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("DialogMessageFactory", () => { | |
describe("createDialogMessage", () => { | |
it("uses the default message when no message is provided", () => { | |
// Arrange | |
const defaultMessage = "foo"; | |
const manager = new DialogMessageFactory(defaultMessage, new Map()); | |
// Act | |
manager.createDialogMessage(undefined); | |
// Assert | |
expect(manager.getDialog()).toEqual(defaultMessage); | |
}); | |
it("uses a message alias when the message matches an alias", () => { | |
// Arrange | |
const alias: [string, string] = ["foo", "bar"]; | |
const manager = new DialogMessageFactory("", new Map([alias])); | |
// Act | |
manager.createDialogMessage(alias[0]); | |
// Assert | |
expect(manager.getDialog()).toEqual(alias[1]); | |
}); | |
it("uses the message when it's provided and doesn't match any alias", () => { | |
// Arrange | |
const manager = new DialogMessageFactory("", new Map()); | |
const message = "foo"; | |
// Act | |
manager.createDialogMessage(message); | |
// Assert | |
expect(manager.getDialog()).toEqual(message); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
interface IDialogMessageFactory { | |
createDialogMessage(message: string | undefined): string; | |
} | |
class DialogMessageFactory implements IDialogMessageFactory { | |
private readonly defaultMessage: string; | |
private readonly messageAliases: Map<string, string> | |
public constructor(defaultMessage: string, messageAliases: Map<string, string>) { | |
this.defaultMessage = defaultMessage; | |
this.messageAliases = messageAliases; | |
} | |
public createDialogMessage(message: string | undefined) { | |
if (message === undefined) { | |
return this.defaultMessage; | |
} | |
const messageAlias = this.messageAliases.get(message); | |
return messageAlias === undefined | |
? messageAlias | |
: message; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("DialogStore", () => { | |
describe("getDialog", () => { | |
it("has an undefined dialog when no message has been set yet", () => { | |
// Arrange | |
const dialogStore = new DialogStore({ | |
(message: string) => message, | |
}); | |
// Act | |
const dialog = dialogStore.getDialog(); | |
// Assert | |
expect(dialog).toBeUndefined(); | |
}); | |
}); | |
describe("showMessage", () => { | |
it("creates a dialog with a generated message when given one", () => { | |
// Arrange | |
const dialogStore = new DialogStore({ | |
(message: string) => `Message: ${message}`, | |
}); | |
// Act | |
dialogStore.showMessage("foo"); | |
// Assert | |
expect(dialogStore.getDialog()).toBeUndefined(); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class DialogStore { | |
private currentDialog?: string; | |
private readonly dialogMessageFactory: IDialogMessageFactory; | |
public constructor(dialogMessageFactory: IDialogMessageFactory) { | |
this.dialogMessageFactory = dialogMessageFactory; | |
} | |
public getDialog(): string | undefined { | |
return this.currentDialog; | |
} | |
public showMessage(message: string | undefined): void { | |
this.currentDialog = this.dialogMessageFactory.createDialogMessage(message); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("FooProcessor", () => { | |
describe("process", () => { | |
it("number multiplication", () => { | |
const processor = new FooProcessor(); | |
const fromPositive = processor.process(2); | |
expect(fromPositive).toEqual(4); | |
const fromNegative = processor.process(-2); | |
expect(fromNegative).toEqual(2); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("FooProcessor", () => { | |
describe("process", () => { | |
it("returns squared input when the input is positive", () => { | |
// Arrange | |
const processor = new FooProcessor(); | |
// Act | |
const fromPositive = processor.process(2); | |
// Assert | |
expect(fromPositive).toEqual(4); | |
}); | |
it("returns absolute input when the input is negative", () => { | |
// Arrange | |
const processor = new FooProcessor(); | |
// Act | |
const fromNegative = processor.process(-2); | |
// Assert | |
expect(fromNegative).toEqual(2); | |
}); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Jest describe, which declares a group of tests | |
describe("Image", () => { | |
// Jest it, which declares a single test | |
it("calls the store's onClick when the image is clicked (expanded)", () => { | |
// Arrange | |
// Jasmine spy that stores calls given to it | |
const spy = jasmine.createSpy(); | |
// (backing store for the image) | |
const store = new ImageStore(spy, ""); | |
// React component shallow-rendered by Enzyme | |
const component = shallow(<Image store={store} />); | |
// Act | |
// Use Enzyme's API hooks to: | |
component | |
.find("img") // Find the simulated <img ... /> (like using jQuery or document.querySelector) | |
.simulate("click") // Simulate a user clicking the img | |
; | |
// Assert | |
// Jasmine assertion that the spy should have been called once | |
expect(spy).toHaveBeenCalledTimes(1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("Image", () => { | |
it("calls the store's onClick when the image is clicked", () => { | |
// Arrange | |
const spy = jasmine.createSpy(); | |
const imageStore = new ImageStore(spy, ""); | |
const component = shallow(<Image store={imageStore} />); | |
// Act | |
rendered.find("img").simulate("click"); | |
// Assert | |
expect(spy).toHaveBeenCalledTimes(1); | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export const Image = observer(({ store }: IStoreProps<ImageStore>) => ( | |
<img onClick={store.onClick} src={store.src} /> | |
)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ImageStore { | |
public constructor( | |
public readonly onClick: () => void, | |
public readonly src: string, | |
) { } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
it("creates details with the Document page mode when given a lookupId", () => { | |
// Arrange | |
const lookupId = "lookupId"; | |
// Act | |
const routeDetails = createRouteDetails(lookupId); | |
// Assert | |
expect(routeDetails).toEqual({ | |
lookupId, | |
pageMode: PageMode.Document, | |
}); | |
}); | |
it("creates details with the My Sways page mode when given an undefined lookupId", () => { | |
// Act | |
const routeDetails = createRouteDetails(undefined); | |
// Assert | |
expect(routeDetails).toEqual({ | |
pageMode: PageMode.MySways, | |
}); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
describe("FooProcessor", () => { | |
describe("process", () => { | |
it("generates a positive square when given a positive number", () => { | |
// Arrange | |
const processor = new FooProcessor(); | |
// Act | |
const result = processor.process(2); | |
// Assert | |
expect(result).toEqual(4); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment