diff --git a/TypeScript/app/gilded-rose.spec.ts b/TypeScript/app/gilded-rose.spec.ts new file mode 100644 index 00000000..e88057e0 --- /dev/null +++ b/TypeScript/app/gilded-rose.spec.ts @@ -0,0 +1,40 @@ +const getUpdateBehaviorMock = jest.fn((item: Item) => new MockBehavior(item)); +const updateMock = jest.fn((item: Item) => item); + +jest.mock("@app/update-behaviors", () => ({ + getUpdateBehaviorFor: getUpdateBehaviorMock, +})); + +import { GildedRose } from "@app/gilded-rose"; +import { Item } from "@app/item"; +import { IUpdateBehavior } from "@app/update-behaviors"; + +export class MockBehavior implements IUpdateBehavior { + constructor(public item: Item) {} + update() { + return updateMock(this.item); + } +} + +describe("Gilded Rose", () => { + it("should have an empty array as items when no constructor parameter is provided", () => { + const gildedRose = new GildedRose(); + expect(gildedRose.items).toEqual([]); + }); + + it("should call the behavior resolver and update function for each item", () => { + const item1 = new Item("item 1", 0, 0); + const item2 = new Item("item 2", 0, 0); + const gildedRose = new GildedRose([item1, item2]); + + gildedRose.updateQuality(); + + expect(getUpdateBehaviorMock).toHaveBeenCalledWith(item1); + expect(getUpdateBehaviorMock).toHaveBeenCalledWith(item2); + + expect(updateMock).toHaveBeenCalledWith(item1); + expect(updateMock).toHaveBeenCalledWith(item2); + }); + + // to implement: "Conjured" items degrade in Quality twice as fast as normal items +}); diff --git a/TypeScript/app/update-behaviors/behavior-resolver.spec.ts b/TypeScript/app/update-behaviors/behavior-resolver.spec.ts new file mode 100644 index 00000000..97f0ce0c --- /dev/null +++ b/TypeScript/app/update-behaviors/behavior-resolver.spec.ts @@ -0,0 +1,18 @@ +import { Item } from "@app/item"; +import { getUpdateBehaviorFor } from "./behavior-resolver"; +import { AgedBrieBehavior } from "./implementations/aged-brie-behavior"; +import { LegacyBehavior } from "./implementations/legacy-behavior"; + +describe("Behavior resolver", () => { + it("should correctly resolve Aged Brie", () => { + expect(getUpdateBehaviorFor(new Item("Aged Brie", 0, 0))).toBeInstanceOf( + AgedBrieBehavior + ); + }); + + it("should correctly resolve the rest to Legacy behavior", () => { + expect( + getUpdateBehaviorFor(new Item("some other item", 0, 0)) + ).toBeInstanceOf(LegacyBehavior); + }); +}); diff --git a/TypeScript/app/update-behaviors/implementations/aged-brie-behavior.spec.ts b/TypeScript/app/update-behaviors/implementations/aged-brie-behavior.spec.ts new file mode 100644 index 00000000..2094db81 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/aged-brie-behavior.spec.ts @@ -0,0 +1,40 @@ +import { Item } from "@app/item"; +import { AgedBrieBehavior } from "./aged-brie-behavior"; + +describe("AgedBrie Behavior", () => { + it("should increase quality of Aged Brie as it gets older", () => { + const behavior = new AgedBrieBehavior(new Item("Aged Brie", 1, 1)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Aged Brie", + sellIn: 0, + quality: 2, + }); + }); + + it("should increase quality of Aged Brie twice as fast after sell in date", () => { + const behavior = new AgedBrieBehavior(new Item("Aged Brie", 0, 1)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Aged Brie", + sellIn: -1, + quality: 3, + }); + }); + + it("should never increase quality of Aged Brie over 50", () => { + const behavior = new AgedBrieBehavior(new Item("Aged Brie", 0, 50)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Aged Brie", + sellIn: -1, + quality: 50, + }); + }); +}); diff --git a/TypeScript/app/update-behaviors/implementations/legacy-behavior.spec.ts b/TypeScript/app/update-behaviors/implementations/legacy-behavior.spec.ts new file mode 100644 index 00000000..c7d86904 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/legacy-behavior.spec.ts @@ -0,0 +1,110 @@ +import { Item } from "@app/item"; +import { LegacyBehavior } from "./legacy-behavior"; + +describe("Legacy Behavior", () => { + it("should degrade sell inn and quality each day", () => { + const behavior = new LegacyBehavior(new Item("standard item", 1, 1)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "standard item", + sellIn: 0, + quality: 0, + }); + }); + + it("should degrade quality twice as fast after sell in date", () => { + const behavior = new LegacyBehavior(new Item("standard item", 0, 2)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "standard item", + sellIn: -1, + quality: 0, + }); + }); + + it("should not degrade quality below 0", () => { + const behavior = new LegacyBehavior(new Item("standard item", 1, 0)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "standard item", + sellIn: 0, + quality: 0, + }); + }); + + it("should not change quality of Sulfuras", () => { + const behavior = new LegacyBehavior( + new Item("Sulfuras, Hand of Ragnaros", 0, 80) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Sulfuras, Hand of Ragnaros", + sellIn: 0, + quality: 80, + }); + }); + + it("should increase quality of Backstage passes by 1 if sell in date is more than 10 days away", () => { + const behavior = new LegacyBehavior( + new Item("Backstage passes to a TAFKAL80ETC concert", 11, 20) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Backstage passes to a TAFKAL80ETC concert", + sellIn: 10, + quality: 21, + }); + }); + + it("should increase quality of Backstage passes by 2 if sell in date is less than 10 days away but more than 5", () => { + const behavior = new LegacyBehavior( + new Item("Backstage passes to a TAFKAL80ETC concert", 9, 20) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Backstage passes to a TAFKAL80ETC concert", + sellIn: 8, + quality: 22, + }); + }); + + it("should increase quality of Backstage passes by 3 if sell in date is less than 5 days away", () => { + const behavior = new LegacyBehavior( + new Item("Backstage passes to a TAFKAL80ETC concert", 4, 20) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Backstage passes to a TAFKAL80ETC concert", + sellIn: 3, + quality: 23, + }); + }); + + it("should drop quality of Backstage passes to 0 after sell in date", () => { + const behavior = new LegacyBehavior( + new Item("Backstage passes to a TAFKAL80ETC concert", 0, 20) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Backstage passes to a TAFKAL80ETC concert", + sellIn: -1, + quality: 0, + }); + }); +}); diff --git a/TypeScript/jest.config.ts b/TypeScript/jest.config.ts index caffa5b4..4b8cecb3 100644 --- a/TypeScript/jest.config.ts +++ b/TypeScript/jest.config.ts @@ -1,13 +1,15 @@ -import { pathsToModuleNameMapper } from "ts-jest"; -import { compilerOptions } from './tsconfig.json' +import { pathsToModuleNameMapper } from "ts-jest"; +import { compilerOptions } from "./tsconfig.json"; export default { - roots: ['/app', '/test/jest'], + roots: ["/app", "/snapshot-tests"], collectCoverage: true, - coverageDirectory: 'coverage', - coverageProvider: 'v8', + coverageDirectory: "coverage", + coverageProvider: "v8", transform: { - '^.+\\.tsx?$': 'ts-jest', + "^.+\\.tsx?$": "ts-jest", }, - moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/' } ), + moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { + prefix: "/", + }), }; diff --git a/TypeScript/package.json b/TypeScript/package.json index b5e53907..0a0c6e57 100644 --- a/TypeScript/package.json +++ b/TypeScript/package.json @@ -3,9 +3,9 @@ "version": "1.0.0", "description": "Gilded Rose kata in TypeScript", "scripts": { - "precompile": "rimraf app/**/*.js test/**/*.js", + "precompile": "rimraf app/**/*.js snapshot-tests/**/*.js", "compile": "tsc", - "pretest": "rimraf app/**/*.js test/**/*.js", + "pretest": "rimraf app/**/*.js snapshot-tests/**/*.js", "test": "jest", "test:watch": "jest --watchAll" }, diff --git a/TypeScript/test/jest/__snapshots__/approvals.spec.ts.snap b/TypeScript/snapshot-tests/__snapshots__/approvals.spec.ts.snap similarity index 100% rename from TypeScript/test/jest/__snapshots__/approvals.spec.ts.snap rename to TypeScript/snapshot-tests/__snapshots__/approvals.spec.ts.snap diff --git a/TypeScript/test/jest/approvals.spec.ts b/TypeScript/snapshot-tests/approvals.spec.ts similarity index 100% rename from TypeScript/test/jest/approvals.spec.ts rename to TypeScript/snapshot-tests/approvals.spec.ts diff --git a/TypeScript/test/jest/gilded-rose.spec.ts b/TypeScript/test/jest/gilded-rose.spec.ts deleted file mode 100644 index f28e1623..00000000 --- a/TypeScript/test/jest/gilded-rose.spec.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { GildedRose } from "@app/gilded-rose"; -import { Item } from "@app/item"; - -describe("Gilded Rose", () => { - it("should have an empty array as items when no constructor parameter is provided", () => { - const gildedRose = new GildedRose(); - expect(gildedRose.items).toEqual([]); - }); - - it("should degrade sell inn and quality each day", () => { - const gildedRose = new GildedRose([new Item("standard item", 1, 1)]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "standard item", - sellIn: 0, - quality: 0, - }); - }); - - it("should degrade quality twice as fast after sell in date", () => { - const gildedRose = new GildedRose([new Item("standard item", 0, 2)]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "standard item", - sellIn: -1, - quality: 0, - }); - }); - - it("should not degrade quality below 0", () => { - const gildedRose = new GildedRose([new Item("standard item", 1, 0)]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "standard item", - sellIn: 0, - quality: 0, - }); - }); - - it("should increase quality of Aged Brie as it gets older", () => { - const gildedRose = new GildedRose([new Item("Aged Brie", 1, 1)]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Aged Brie", - sellIn: 0, - quality: 2, - }); - }); - - it("should increase quality of Aged Brie twice as fast after sell in date", () => { - const gildedRose = new GildedRose([new Item("Aged Brie", 0, 1)]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Aged Brie", - sellIn: -1, - quality: 3, - }); - }); - - it("should never increase quality of Aged Brie over 50", () => { - const gildedRose = new GildedRose([new Item("Aged Brie", 0, 50)]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Aged Brie", - sellIn: -1, - quality: 50, - }); - }); - - it("should not change quality of Sulfuras", () => { - const gildedRose = new GildedRose([ - new Item("Sulfuras, Hand of Ragnaros", 0, 80), - ]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Sulfuras, Hand of Ragnaros", - sellIn: 0, - quality: 80, - }); - }); - - it("should increase quality of Backstage passes by 1 if sell in date is more than 10 days away", () => { - const gildedRose = new GildedRose([ - new Item("Backstage passes to a TAFKAL80ETC concert", 11, 20), - ]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Backstage passes to a TAFKAL80ETC concert", - sellIn: 10, - quality: 21, - }); - }); - - it("should increase quality of Backstage passes by 2 if sell in date is less than 10 days away but more than 5", () => { - const gildedRose = new GildedRose([ - new Item("Backstage passes to a TAFKAL80ETC concert", 9, 20), - ]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Backstage passes to a TAFKAL80ETC concert", - sellIn: 8, - quality: 22, - }); - }); - - it("should increase quality of Backstage passes by 3 if sell in date is less than 5 days away", () => { - const gildedRose = new GildedRose([ - new Item("Backstage passes to a TAFKAL80ETC concert", 4, 20), - ]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Backstage passes to a TAFKAL80ETC concert", - sellIn: 3, - quality: 23, - }); - }); - - it("should drop quality of Backstage passes to 0 after sell in date", () => { - const gildedRose = new GildedRose([ - new Item("Backstage passes to a TAFKAL80ETC concert", 0, 20), - ]); - - const items = gildedRose.updateQuality(); - - expect(items[0]).toMatchObject({ - name: "Backstage passes to a TAFKAL80ETC concert", - sellIn: -1, - quality: 0, - }); - }); - - // to implement: "Conjured" items degrade in Quality twice as fast as normal items -});