diff --git a/TypeScript/.mocharc.js b/TypeScript/.mocharc.js deleted file mode 100644 index 9ae39f77..00000000 --- a/TypeScript/.mocharc.js +++ /dev/null @@ -1,11 +0,0 @@ -"use strict"; - -module.exports = { - require: [ - "ts-node/register", - "tsconfig-paths/register", - "source-map-support/register" - ], - recursive: true, - spec: "test/mocha/*.spec.ts" -} diff --git a/TypeScript/.nycrc.js b/TypeScript/.nycrc.js deleted file mode 100644 index 3b19d56e..00000000 --- a/TypeScript/.nycrc.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - extension: [ - ".ts" - ], - exclude: [ - "**/*.d.ts", - "test/**", - "/*.js" - ], - require: [ - "ts-node/register" - ], - reporter: [ - "html", - "text" - ] -} diff --git a/TypeScript/app/config.ts b/TypeScript/app/config.ts new file mode 100644 index 00000000..44cedf34 --- /dev/null +++ b/TypeScript/app/config.ts @@ -0,0 +1,3 @@ +export const config = { + maxQuality: 50, +}; diff --git a/TypeScript/app/gilded-rose.spec.ts b/TypeScript/app/gilded-rose.spec.ts new file mode 100644 index 00000000..2bf7175e --- /dev/null +++ b/TypeScript/app/gilded-rose.spec.ts @@ -0,0 +1,38 @@ +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); + }); +}); diff --git a/TypeScript/app/gilded-rose.ts b/TypeScript/app/gilded-rose.ts index db58d678..caee7ef2 100644 --- a/TypeScript/app/gilded-rose.ts +++ b/TypeScript/app/gilded-rose.ts @@ -1,16 +1,9 @@ -export class Item { - name: string; - sellIn: number; - quality: number; - - constructor(name, sellIn, quality) { - this.name = name; - this.sellIn = sellIn; - this.quality = quality; - } -} +import { Item } from "@app/item"; +import { getUpdateBehaviorFor } from "@app/update-behaviors"; export class GildedRose { + // also can't edit this because of the kata rules. + // But I prefer typing this as : Item[] items: Array; constructor(items = [] as Array) { @@ -18,52 +11,8 @@ export class GildedRose { } updateQuality() { - for (let i = 0; i < this.items.length; i++) { - if (this.items[i].name != 'Aged Brie' && this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { - if (this.items[i].quality > 0) { - if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { - this.items[i].quality = this.items[i].quality - 1 - } - } - } else { - if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 - if (this.items[i].name == 'Backstage passes to a TAFKAL80ETC concert') { - if (this.items[i].sellIn < 11) { - if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 - } - } - if (this.items[i].sellIn < 6) { - if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 - } - } - } - } - } - if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { - this.items[i].sellIn = this.items[i].sellIn - 1; - } - if (this.items[i].sellIn < 0) { - if (this.items[i].name != 'Aged Brie') { - if (this.items[i].name != 'Backstage passes to a TAFKAL80ETC concert') { - if (this.items[i].quality > 0) { - if (this.items[i].name != 'Sulfuras, Hand of Ragnaros') { - this.items[i].quality = this.items[i].quality - 1 - } - } - } else { - this.items[i].quality = this.items[i].quality - this.items[i].quality - } - } else { - if (this.items[i].quality < 50) { - this.items[i].quality = this.items[i].quality + 1 - } - } - } - } - - return this.items; + return this.items.map((item) => { + return getUpdateBehaviorFor(item).update(); + }); } } diff --git a/TypeScript/app/item.ts b/TypeScript/app/item.ts new file mode 100644 index 00000000..5bad4d89 --- /dev/null +++ b/TypeScript/app/item.ts @@ -0,0 +1,18 @@ +export class Item { + name: string; + sellIn: number; + quality: number; + + // can't edit this constructor because of the kata rules. + // but I would change the constructor to take a javaScript object. + // It makes the consumer code more readable. + // e.g. new Item({ name: "standard item", sellIn: 0, quality: 2 }) + // instead of new Item("standard item", 0, 2) + + // I would also type the parameters, because now they are implicitly any. + constructor(name, sellIn, quality) { + this.name = name; + this.sellIn = sellIn; + this.quality = quality; + } +} 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..fe026f64 --- /dev/null +++ b/TypeScript/app/update-behaviors/behavior-resolver.spec.ts @@ -0,0 +1,40 @@ +import { Item } from "@app/item"; +import { getUpdateBehaviorFor } from "./behavior-resolver"; +import { AgedBrieBehavior } from "./implementations/aged-brie/aged-brie-behavior"; +import { DefaultBehavior } from "./implementations/default/default-behavior"; +import { BackstagePassBehavior } from "./implementations/backstage-pass/backstage-pass-behavior"; +import { LegendaryItemBehavior } from "./implementations/legendary-item/legendary-item-behavior"; +import { ConjuredItemBehavior } from "./implementations/conjured-item/conjured-item-behavior"; + +describe("Behavior resolver", () => { + it("should correctly resolve Aged Brie", () => { + expect(getUpdateBehaviorFor(new Item("Aged Brie", 0, 0))).toBeInstanceOf( + AgedBrieBehavior + ); + }); + + it("should correctly resolve Backstage Passes", () => { + expect( + getUpdateBehaviorFor( + new Item("Backstage passes to a TAFKAL80ETC concert", 0, 0) + ) + ).toBeInstanceOf(BackstagePassBehavior); + }); + + it("should correctly resolve Legendary Items", () => { + expect( + getUpdateBehaviorFor(new Item("Sulfuras, Hand of Ragnaros", 0, 0)) + ).toBeInstanceOf(LegendaryItemBehavior); + }); + it("should correctly resolve Conjured Items", () => { + expect( + getUpdateBehaviorFor(new Item("Conjured Mana Cake", 0, 0)) + ).toBeInstanceOf(ConjuredItemBehavior); + }); + + it("should correctly resolve the rest to Legacy behavior", () => { + expect( + getUpdateBehaviorFor(new Item("some other item", 0, 0)) + ).toBeInstanceOf(DefaultBehavior); + }); +}); diff --git a/TypeScript/app/update-behaviors/behavior-resolver.ts b/TypeScript/app/update-behaviors/behavior-resolver.ts new file mode 100644 index 00000000..c638e0ad --- /dev/null +++ b/TypeScript/app/update-behaviors/behavior-resolver.ts @@ -0,0 +1,22 @@ +import { Item } from "@app/item"; +import { IUpdateBehavior } from "./update-behavior.interface"; +import { DefaultBehavior } from "./implementations/default/default-behavior"; +import { AgedBrieBehavior } from "./implementations/aged-brie/aged-brie-behavior"; +import { BackstagePassBehavior } from "./implementations/backstage-pass/backstage-pass-behavior"; +import { LegendaryItemBehavior } from "./implementations/legendary-item/legendary-item-behavior"; +import { ConjuredItemBehavior } from "./implementations/conjured-item/conjured-item-behavior"; + +export function getUpdateBehaviorFor(item: Item): IUpdateBehavior { + switch (item.name) { + case "Aged Brie": + return new AgedBrieBehavior(item); + case "Backstage passes to a TAFKAL80ETC concert": + return new BackstagePassBehavior(item); + case "Sulfuras, Hand of Ragnaros": + return new LegendaryItemBehavior(item); + case "Conjured Mana Cake": + return new ConjuredItemBehavior(item); + default: + return new DefaultBehavior(item); + } +} diff --git a/TypeScript/app/update-behaviors/implementations/aged-brie/aged-brie-behavior.spec.ts b/TypeScript/app/update-behaviors/implementations/aged-brie/aged-brie-behavior.spec.ts new file mode 100644 index 00000000..2094db81 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/aged-brie/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/aged-brie/aged-brie-behavior.ts b/TypeScript/app/update-behaviors/implementations/aged-brie/aged-brie-behavior.ts new file mode 100644 index 00000000..9e3ca51e --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/aged-brie/aged-brie-behavior.ts @@ -0,0 +1,22 @@ +import { config } from "@app/config"; +import { Item } from "@app/item"; +import { IUpdateBehavior } from "@app/update-behaviors"; + +export class AgedBrieBehavior implements IUpdateBehavior { + constructor(private item: Item) {} + + update(): Item { + const isPastSellInDay = this.item.sellIn <= 0; + + const amountToAdd = isPastSellInDay ? 2 : 1; + + this.item.quality = Math.min( + config.maxQuality, + this.item.quality + amountToAdd + ); + + this.item.sellIn -= 1; + + return this.item; + } +} diff --git a/TypeScript/app/update-behaviors/implementations/backstage-pass/backstage-pass-behavior.spec.ts b/TypeScript/app/update-behaviors/implementations/backstage-pass/backstage-pass-behavior.spec.ts new file mode 100644 index 00000000..aca4dbff --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/backstage-pass/backstage-pass-behavior.spec.ts @@ -0,0 +1,74 @@ +import { Item } from "@app/item"; +import { BackstagePassBehavior } from "./backstage-pass-behavior"; + +describe("Backstage Pass Behavior", () => { + it("should increase quality of Backstage passes by 1 if sell in date is more than 10 days away", () => { + const behavior = new BackstagePassBehavior( + 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 BackstagePassBehavior( + 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 BackstagePassBehavior( + 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 BackstagePassBehavior( + 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, + }); + }); + + it("should not increase over 50", () => { + const behavior = new BackstagePassBehavior( + new Item("Backstage passes to a TAFKAL80ETC concert", 4, 50) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Backstage passes to a TAFKAL80ETC concert", + sellIn: 3, + quality: 50, + }); + }); +}); diff --git a/TypeScript/app/update-behaviors/implementations/backstage-pass/backstage-pass-behavior.ts b/TypeScript/app/update-behaviors/implementations/backstage-pass/backstage-pass-behavior.ts new file mode 100644 index 00000000..c0996df4 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/backstage-pass/backstage-pass-behavior.ts @@ -0,0 +1,30 @@ +import { config } from "@app/config"; +import { Item } from "@app/item"; +import { IUpdateBehavior } from "@app/update-behaviors"; + +export class BackstagePassBehavior implements IUpdateBehavior { + constructor(private item: Item) {} + update(): Item { + const sellIn = this.item.sellIn; + const amountToIncrease = this.#getAmountToIncrease(sellIn); + + this.item.quality = Math.min( + this.item.quality + amountToIncrease, + config.maxQuality + ); + + if (sellIn <= 0) { + this.item.quality = 0; + } + + this.item.sellIn -= 1; + + return this.item; + } + + #getAmountToIncrease(sellIn: number): number { + if (sellIn <= 5) return 3; + if (sellIn <= 10) return 2; + return 1; + } +} diff --git a/TypeScript/app/update-behaviors/implementations/conjured-item/conjured-item-behavior.spec.ts b/TypeScript/app/update-behaviors/implementations/conjured-item/conjured-item-behavior.spec.ts new file mode 100644 index 00000000..7f237f7b --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/conjured-item/conjured-item-behavior.spec.ts @@ -0,0 +1,59 @@ +import { Item } from "@app/item"; +import { ConjuredItemBehavior } from "./conjured-item-behavior"; + +describe("Conjured Item Behavior", () => { + it("should degrade quality with 2 and sellIn with 1 when sellIn is over 0", () => { + const behavior = new ConjuredItemBehavior( + new Item("Conjured Mana Cake", 1, 4) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Conjured Mana Cake", + sellIn: 0, + quality: 2, + }); + }); + it("should degrade quality with 4 and sellin with 1 when sellIn is equal to zero", () => { + const behavior = new ConjuredItemBehavior( + new Item("Conjured Mana Cake", 0, 5) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Conjured Mana Cake", + sellIn: -1, + quality: 1, + }); + }); + + it("should degrade quality with 4 and sellin with 1 when sellIn is under zero", () => { + const behavior = new ConjuredItemBehavior( + new Item("Conjured Mana Cake", -1, 5) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Conjured Mana Cake", + sellIn: -2, + quality: 1, + }); + }); + + it("shouldn't degrade quality under 0", () => { + const behavior = new ConjuredItemBehavior( + new Item("Conjured Mana Cake", 1, 1) + ); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "Conjured Mana Cake", + sellIn: 0, + quality: 0, + }); + }); +}); diff --git a/TypeScript/app/update-behaviors/implementations/conjured-item/conjured-item-behavior.ts b/TypeScript/app/update-behaviors/implementations/conjured-item/conjured-item-behavior.ts new file mode 100644 index 00000000..007eb6e1 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/conjured-item/conjured-item-behavior.ts @@ -0,0 +1,16 @@ +import { Item } from "@app/item"; +import { IUpdateBehavior } from "@app/update-behaviors/update-behavior.interface"; + +export class ConjuredItemBehavior implements IUpdateBehavior { + constructor(private item: Item) {} + + update(): Item { + const amountToSubtract = this.item.sellIn <= 0 ? 4 : 2; + + this.item.quality = Math.max(this.item.quality - amountToSubtract, 0); + + this.item.sellIn -= 1; + + return this.item; + } +} diff --git a/TypeScript/app/update-behaviors/implementations/default/default-behavior.spec.ts b/TypeScript/app/update-behaviors/implementations/default/default-behavior.spec.ts new file mode 100644 index 00000000..92f60763 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/default/default-behavior.spec.ts @@ -0,0 +1,40 @@ +import { Item } from "@app/item"; +import { DefaultBehavior } from "./default-behavior"; + +describe("Default Behavior", () => { + it("should degrade sell inn and quality each day", () => { + const behavior = new DefaultBehavior(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 DefaultBehavior(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 DefaultBehavior(new Item("standard item", 1, 0)); + + const result = behavior.update(); + + expect(result).toMatchObject({ + name: "standard item", + sellIn: 0, + quality: 0, + }); + }); +}); diff --git a/TypeScript/app/update-behaviors/implementations/default/default-behavior.ts b/TypeScript/app/update-behaviors/implementations/default/default-behavior.ts new file mode 100644 index 00000000..70e07a3f --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/default/default-behavior.ts @@ -0,0 +1,15 @@ +import { Item } from "@app/item"; +import { IUpdateBehavior } from "../../update-behavior.interface"; + +export class DefaultBehavior implements IUpdateBehavior { + constructor(private item: Item) {} + + update(): Item { + const amountToSubtract = this.item.sellIn <= 0 ? 2 : 1; + this.item.quality = Math.max(this.item.quality - amountToSubtract, 0); + + this.item.sellIn -= 1; + + return this.item; + } +} diff --git a/TypeScript/app/update-behaviors/implementations/legendary-item/legendary-item-behavior.ts b/TypeScript/app/update-behaviors/implementations/legendary-item/legendary-item-behavior.ts new file mode 100644 index 00000000..cfe2750c --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/legendary-item/legendary-item-behavior.ts @@ -0,0 +1,13 @@ +import { config } from "@app/config"; +import { Item } from "@app/item"; +import { IUpdateBehavior } from "@app/update-behaviors/update-behavior.interface"; + +export class LegendaryItemBehavior implements IUpdateBehavior { + constructor(public item: Item) {} + update(): Item { + if (this.item.quality !== 80) { + throw new Error("A Legendary Item cannot have a quality other than 80"); + } + return this.item; + } +} diff --git a/TypeScript/app/update-behaviors/implementations/legendary-item/legendary-item.spec.ts b/TypeScript/app/update-behaviors/implementations/legendary-item/legendary-item.spec.ts new file mode 100644 index 00000000..f3fef643 --- /dev/null +++ b/TypeScript/app/update-behaviors/implementations/legendary-item/legendary-item.spec.ts @@ -0,0 +1,28 @@ +import { Item } from "@app/item"; +import { LegendaryItemBehavior } from "./legendary-item-behavior"; + +describe("Legendary Item Behavior", () => { + it("should keep items of quality 80 the same", () => { + const behavior = new LegendaryItemBehavior( + 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 throw an error when a legendary item doesn't have a quality of 80", () => { + const behavior = new LegendaryItemBehavior( + new Item("Sulfuras, Hand of Ragnaros", 0, 5) + ); + + expect(() => behavior.update()).toThrow( + "A Legendary Item cannot have a quality other than 80" + ); + }); +}); diff --git a/TypeScript/app/update-behaviors/index.ts b/TypeScript/app/update-behaviors/index.ts new file mode 100644 index 00000000..bdaa4d9a --- /dev/null +++ b/TypeScript/app/update-behaviors/index.ts @@ -0,0 +1,2 @@ +export * from "./update-behavior.interface"; +export * from "./behavior-resolver"; diff --git a/TypeScript/app/update-behaviors/update-behavior.interface.ts b/TypeScript/app/update-behaviors/update-behavior.interface.ts new file mode 100644 index 00000000..351156c1 --- /dev/null +++ b/TypeScript/app/update-behaviors/update-behavior.interface.ts @@ -0,0 +1,5 @@ +import { Item } from "@app/item"; + +export interface IUpdateBehavior { + update: () => Item; +} 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 c7c597e3..0a0c6e57 100644 --- a/TypeScript/package.json +++ b/TypeScript/package.json @@ -3,33 +3,23 @@ "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", - "test:jest": "jest", - "test:jest:watch": "jest --watchAll", - "test:mocha": "nyc mocha", - "test:vitest": "vitest --coverage" + "pretest": "rimraf app/**/*.js snapshot-tests/**/*.js", + "test": "jest", + "test:watch": "jest --watchAll" }, "license": "MIT", "private": true, "devDependencies": { - "@types/chai": "^4.2.22", "@types/jest": "^29.4.0", - "@types/mocha": "^10.0.1", "@types/node": "^18.14.0", - "@vitest/coverage-istanbul": "^0.28.5", - "chai": "^4.3.4", "jest": "^29.4.3", - "mocha": "^10.2.0", - "nyc": "~15.1.0", "rimraf": "^4.1.2", "source-map-support": "^0.5.20", "ts-jest": "^29.0.5", "ts-node": "^10.9.1", "tsconfig-paths": "^4.1.2", - "typescript": "^4.4.4", - "vite-tsconfig-paths": "^4.0.5", - "vitest": "^0.28.5" + "typescript": "^4.4.4" } } diff --git a/TypeScript/snapshot-tests/__snapshots__/approvals.spec.ts.snap b/TypeScript/snapshot-tests/__snapshots__/approvals.spec.ts.snap new file mode 100644 index 00000000..3f299ad2 --- /dev/null +++ b/TypeScript/snapshot-tests/__snapshots__/approvals.spec.ts.snap @@ -0,0 +1,1501 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 1`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 19, + "sellIn": 9, + }, + Item { + "name": "Aged Brie", + "quality": 1, + "sellIn": 1, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 6, + "sellIn": 4, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 21, + "sellIn": 14, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 9, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 4, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 4, + "sellIn": 2, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 2`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 18, + "sellIn": 8, + }, + Item { + "name": "Aged Brie", + "quality": 2, + "sellIn": 0, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 5, + "sellIn": 3, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 22, + "sellIn": 13, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 8, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 3, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 2, + "sellIn": 1, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 3`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 17, + "sellIn": 7, + }, + Item { + "name": "Aged Brie", + "quality": 4, + "sellIn": -1, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 4, + "sellIn": 2, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 23, + "sellIn": 12, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 7, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 2, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": 0, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 4`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 16, + "sellIn": 6, + }, + Item { + "name": "Aged Brie", + "quality": 6, + "sellIn": -2, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 3, + "sellIn": 1, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 24, + "sellIn": 11, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 6, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 1, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -1, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 5`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 15, + "sellIn": 5, + }, + Item { + "name": "Aged Brie", + "quality": 8, + "sellIn": -3, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 2, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 25, + "sellIn": 10, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 5, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 0, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -2, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 6`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 14, + "sellIn": 4, + }, + Item { + "name": "Aged Brie", + "quality": 10, + "sellIn": -4, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -1, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 27, + "sellIn": 9, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 4, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -1, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -3, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 7`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 13, + "sellIn": 3, + }, + Item { + "name": "Aged Brie", + "quality": 12, + "sellIn": -5, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -2, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 29, + "sellIn": 8, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 3, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -2, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -4, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 8`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 12, + "sellIn": 2, + }, + Item { + "name": "Aged Brie", + "quality": 14, + "sellIn": -6, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -3, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 31, + "sellIn": 7, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 2, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -3, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -5, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 9`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 11, + "sellIn": 1, + }, + Item { + "name": "Aged Brie", + "quality": 16, + "sellIn": -7, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -4, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 33, + "sellIn": 6, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -4, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -6, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 10`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 10, + "sellIn": 0, + }, + Item { + "name": "Aged Brie", + "quality": 18, + "sellIn": -8, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -5, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 35, + "sellIn": 5, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 0, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -5, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -7, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 11`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 8, + "sellIn": -1, + }, + Item { + "name": "Aged Brie", + "quality": 20, + "sellIn": -9, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -6, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 38, + "sellIn": 4, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -6, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -8, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 12`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 6, + "sellIn": -2, + }, + Item { + "name": "Aged Brie", + "quality": 22, + "sellIn": -10, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -7, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 41, + "sellIn": 3, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -2, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -7, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -9, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 13`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 4, + "sellIn": -3, + }, + Item { + "name": "Aged Brie", + "quality": 24, + "sellIn": -11, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -8, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 44, + "sellIn": 2, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -3, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -8, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -10, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 14`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 2, + "sellIn": -4, + }, + Item { + "name": "Aged Brie", + "quality": 26, + "sellIn": -12, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -9, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 47, + "sellIn": 1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -4, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -9, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -11, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 15`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -5, + }, + Item { + "name": "Aged Brie", + "quality": 28, + "sellIn": -13, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -10, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 50, + "sellIn": 0, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -5, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -10, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -12, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 16`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -6, + }, + Item { + "name": "Aged Brie", + "quality": 30, + "sellIn": -14, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -11, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -6, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -11, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -13, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 17`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -7, + }, + Item { + "name": "Aged Brie", + "quality": 32, + "sellIn": -15, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -12, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -2, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -7, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -12, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -14, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 18`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -8, + }, + Item { + "name": "Aged Brie", + "quality": 34, + "sellIn": -16, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -13, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -3, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -8, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -13, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -15, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 19`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -9, + }, + Item { + "name": "Aged Brie", + "quality": 36, + "sellIn": -17, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -14, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -4, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -9, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -14, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -16, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 20`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -10, + }, + Item { + "name": "Aged Brie", + "quality": 38, + "sellIn": -18, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -15, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -5, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -10, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -15, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -17, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 21`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -11, + }, + Item { + "name": "Aged Brie", + "quality": 40, + "sellIn": -19, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -16, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -6, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -11, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -16, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -18, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 22`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -12, + }, + Item { + "name": "Aged Brie", + "quality": 42, + "sellIn": -20, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -17, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -7, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -12, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -17, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -19, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 23`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -13, + }, + Item { + "name": "Aged Brie", + "quality": 44, + "sellIn": -21, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -18, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -8, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -13, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -18, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -20, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 24`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -14, + }, + Item { + "name": "Aged Brie", + "quality": 46, + "sellIn": -22, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -19, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -9, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -14, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -19, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -21, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 25`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -15, + }, + Item { + "name": "Aged Brie", + "quality": 48, + "sellIn": -23, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -20, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -10, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -15, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -20, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -22, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 26`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -16, + }, + Item { + "name": "Aged Brie", + "quality": 50, + "sellIn": -24, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -21, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -11, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -16, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -21, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -23, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 27`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -17, + }, + Item { + "name": "Aged Brie", + "quality": 50, + "sellIn": -25, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -22, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -12, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -17, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -22, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -24, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 28`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -18, + }, + Item { + "name": "Aged Brie", + "quality": 50, + "sellIn": -26, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -23, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -13, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -18, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -23, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -25, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 29`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -19, + }, + Item { + "name": "Aged Brie", + "quality": 50, + "sellIn": -27, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -24, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -14, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -19, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -24, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -26, + }, +] +`; + +exports[`Gilded Rose Approval should match the snapshot for thirty Days 30`] = ` +[ + Item { + "name": "+5 Dexterity Vest", + "quality": 0, + "sellIn": -20, + }, + Item { + "name": "Aged Brie", + "quality": 50, + "sellIn": -28, + }, + Item { + "name": "Elixir of the Mongoose", + "quality": 0, + "sellIn": -25, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": 0, + }, + Item { + "name": "Sulfuras, Hand of Ragnaros", + "quality": 80, + "sellIn": -1, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -15, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -20, + }, + Item { + "name": "Backstage passes to a TAFKAL80ETC concert", + "quality": 0, + "sellIn": -25, + }, + Item { + "name": "Conjured Mana Cake", + "quality": 0, + "sellIn": -27, + }, +] +`; diff --git a/TypeScript/snapshot-tests/approvals.spec.ts b/TypeScript/snapshot-tests/approvals.spec.ts new file mode 100644 index 00000000..b33f47c0 --- /dev/null +++ b/TypeScript/snapshot-tests/approvals.spec.ts @@ -0,0 +1,28 @@ +import { GildedRose } from "@app/gilded-rose"; +import { Item } from "@app/item"; + +describe("Gilded Rose Approval", () => { + it("should match the snapshot for thirty Days", () => { + const items = [ + new Item("+5 Dexterity Vest", 10, 20), // + new Item("Aged Brie", 2, 0), // + new Item("Elixir of the Mongoose", 5, 7), // + new Item("Sulfuras, Hand of Ragnaros", 0, 80), // + new Item("Sulfuras, Hand of Ragnaros", -1, 80), + new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), + new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), + new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), + // this conjured item does not work properly yet + new Item("Conjured Mana Cake", 3, 6), + ]; + + const gildedRose = new GildedRose(items); + + const days = 30; + + for (let i = 0; i < days; i++) { + const updatedItems = gildedRose.updateQuality(); + expect(updatedItems).toMatchSnapshot(); + } + }); +}); diff --git a/TypeScript/test/golden-master-text-test.ts b/TypeScript/test/golden-master-text-test.ts deleted file mode 100644 index 378f78d5..00000000 --- a/TypeScript/test/golden-master-text-test.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Item, GildedRose } from '../app/gilded-rose'; - -console.log("OMGHAI!") - -const items = [ - new Item("+5 Dexterity Vest", 10, 20), // - new Item("Aged Brie", 2, 0), // - new Item("Elixir of the Mongoose", 5, 7), // - new Item("Sulfuras, Hand of Ragnaros", 0, 80), // - new Item("Sulfuras, Hand of Ragnaros", -1, 80), - new Item("Backstage passes to a TAFKAL80ETC concert", 15, 20), - new Item("Backstage passes to a TAFKAL80ETC concert", 10, 49), - new Item("Backstage passes to a TAFKAL80ETC concert", 5, 49), - // this conjured item does not work properly yet - new Item("Conjured Mana Cake", 3, 6)]; - - -const gildedRose = new GildedRose(items); - -let days: number = 2; -if (process.argv.length > 2) { - days = +process.argv[2]; - } - -for (let i = 0; i < days + 1; i++) { - console.log("-------- day " + i + " --------"); - console.log("name, sellIn, quality"); - items.forEach(element => { - console.log(element.name + ', ' + element.sellIn + ', ' + element.quality); - - }); - console.log(); - gildedRose.updateQuality(); -} diff --git a/TypeScript/test/jest/approvals.spec.ts b/TypeScript/test/jest/approvals.spec.ts deleted file mode 100644 index bb7f45f9..00000000 --- a/TypeScript/test/jest/approvals.spec.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Item, GildedRose } from '@/gilded-rose'; - -/** - * This unit test uses [Jest Snapshot](https://goo.gl/fbAQLP). - * - * There are two test cases here with different styles: - *
  • "foo" is more similar to the unit test from the 'Java' version - *
  • "thirtyDays" is more similar to the TextTest from the 'Java' version - * - * I suggest choosing one style to develop and deleting the other. - */ - -describe('Gilded Rose Approval', () => { - - let gameConsoleOutput: string; - let originalConsoleLog: (message: any) => void; - let originalProcessArgv: string[] - - function gameConsoleLog(msg: string) { - if (msg) { - gameConsoleOutput += msg; - } - gameConsoleOutput += "\n"; - } - - beforeEach(() => { - // prepare capturing console.log to our own gameConsoleLog. - gameConsoleOutput = ""; - originalConsoleLog = console.log; - console.log = gameConsoleLog; - originalProcessArgv = process.argv; - }); - - afterEach(() => { - // reset original console.log - console.log = originalConsoleLog; - process.argv = originalProcessArgv; - }); - - it('should foo', () => { - const gildedRose = new GildedRose([new Item('foo', 0, 0)]); - const items = gildedRose.updateQuality(); - - expect(items).toMatchSnapshot(); - }); - - it('should thirtyDays', () => { - process.argv = ["", " { - it('should foo', () => { - const gildedRose = new GildedRose([new Item('foo', 0, 0)]); - const items = gildedRose.updateQuality(); - expect(items[0].name).toBe('fixme'); - }); -}); diff --git a/TypeScript/test/mocha/gilded-rose.spec.ts b/TypeScript/test/mocha/gilded-rose.spec.ts deleted file mode 100644 index 02cd24c5..00000000 --- a/TypeScript/test/mocha/gilded-rose.spec.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { expect } from 'chai'; -import { Item, GildedRose } from '@/gilded-rose'; - -describe('Gilded Rose', () => { - it('should foo', () => { - const gildedRose = new GildedRose([new Item('foo', 0, 0)]); - const items = gildedRose.updateQuality(); - expect(items[0].name).to.equal('fixme'); - }); -}); diff --git a/TypeScript/test/vitest/approvals.spec.ts b/TypeScript/test/vitest/approvals.spec.ts deleted file mode 100644 index 858f4a22..00000000 --- a/TypeScript/test/vitest/approvals.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { execSync } from 'node:child_process'; -import { Item, GildedRose } from '@/gilded-rose'; - -/** - * This test uses Vitest Snapshot, similar to [Jest Snapshot](https://goo.gl/fbAQLP). - * - * There are two test cases here with different styles: - *
  • "foo" is more similar to the unit test from the 'Java' version - *
  • "thirtyDays" is more similar to the TextTest from the 'Java' version - * - * I suggest choosing one style to develop and deleting the other. - */ - -describe('Gilded Rose Approval', () => { - it('should foo', () => { - const gildedRose = new GildedRose([new Item('foo', 0, 0)]); - const items = gildedRose.updateQuality(); - - expect(items).toMatchSnapshot(); - }); - - it('should thirtyDays', () => { - const consoleOutput = execSync( - 'ts-node test/golden-master-text-test.ts 30', - { encoding: 'utf-8' } - ); - - expect(consoleOutput).toMatchSnapshot(); - }); -}); diff --git a/TypeScript/test/vitest/gilded-rose.spec.ts b/TypeScript/test/vitest/gilded-rose.spec.ts deleted file mode 100644 index 65330750..00000000 --- a/TypeScript/test/vitest/gilded-rose.spec.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Item, GildedRose } from '@/gilded-rose'; - -describe('Gilded Rose', () => { - it('should foo', () => { - const gildedRose = new GildedRose([new Item('foo', 0, 0)]); - const items = gildedRose.updateQuality(); - expect(items[0].name).toBe('fixme'); - }); -}); diff --git a/TypeScript/texttest_rig.py b/TypeScript/texttest_rig.py deleted file mode 100644 index 0cd59ad1..00000000 --- a/TypeScript/texttest_rig.py +++ /dev/null @@ -1,14 +0,0 @@ -#!/usr/bin/env python -""" -This script uses npx to execute the TextTest Fixture for TypeScript. -It is designed to be used by TextTest and specified in the file 'texttests/config.gr' in this repo. -It is more convenient for TextTest to use since npx needs -several arguments in addition to the one the TextTest fixture needs. -""" -import os -import subprocess -import sys - -args = " ".join(sys.argv[1:]) -TEXTTEST_HOME = os.environ.get("TEXTTEST_HOME", os.getcwd()) -subprocess.run(f"npx ts-node {TEXTTEST_HOME}/TypeScript/test/golden-master-text-test.ts {args}", shell=True) diff --git a/TypeScript/tsconfig.json b/TypeScript/tsconfig.json index d2922795..eff4f0f1 100644 --- a/TypeScript/tsconfig.json +++ b/TypeScript/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "commonjs", - "target": "es5", + "target": "es2022", "strict": true, "noImplicitAny": false, "sourceMap": true, @@ -9,12 +9,8 @@ "resolveJsonModule": true, "esModuleInterop": true, "paths": { - "@/*": [ - "app/*" - ] + "@app/*": ["app/*"] } }, - "exclude": [ - "node_modules" - ] + "exclude": ["node_modules"] } diff --git a/TypeScript/vitest.config.ts b/TypeScript/vitest.config.ts deleted file mode 100644 index 73488c68..00000000 --- a/TypeScript/vitest.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import {defineConfig} from 'vitest/config'; -import tsconfigPaths from 'vite-tsconfig-paths'; - -export default defineConfig({ - plugins: [tsconfigPaths()], - test: { - globals: true, - include: ['test/vitest/**/*.{spec,test}.{js,ts}'], - coverage: { - provider: 'istanbul', - reporter: ['text', 'html'] - } - }, -});