diff --git a/TypeScript/app/d/Assignment.md b/TypeScript/app/d/Assignment.md index 711668c..802483e 100644 --- a/TypeScript/app/d/Assignment.md +++ b/TypeScript/app/d/Assignment.md @@ -33,3 +33,5 @@ logic is in `ShippingCost`. * Bring `ShippingCost` under test. Make sure to cover all paths in the core logic. * There is an existing `ShippingCostTest` with a first test case which might or might not work. * You cannot change `RestCountriesAPI` because it is used by other teams as well. + +(This is a copied document - do not edit!) diff --git a/TypeScript/app/d/money.ts b/TypeScript/app/d/money.ts index 86ea9e2..f81de75 100644 --- a/TypeScript/app/d/money.ts +++ b/TypeScript/app/d/money.ts @@ -1,8 +1,5 @@ export class Money { - public static readonly ONE_THOUSAND: Money = new Money(1000); - public static readonly ONE_HUNDRED: Money = new Money(100); - value: number; constructor(value: number | string) { @@ -13,19 +10,11 @@ export class Money { } } - add(other: Money): Money { - return new Money(this.value + other.value); - } - - percentage(p: number): Money { + percentage(p: number): Money { return new Money((this.value * p / 100).toFixed(2)); } - moreThan(other: Money): boolean { - return this.value > other.value; - } - - format(): string { + format(): string { return this.value.toFixed(2); } diff --git a/TypeScript/app/d/rest-countries-api.ts b/TypeScript/app/d/rest-countries-api.ts index 6b19db0..3fd69bc 100644 --- a/TypeScript/app/d/rest-countries-api.ts +++ b/TypeScript/app/d/rest-countries-api.ts @@ -1,4 +1,4 @@ -import {Country} from "./country"; +import { Country } from "./country"; import fetch from 'node-fetch'; @@ -16,8 +16,8 @@ interface RestCountry { } export class RestCountriesAPI { - readonly HOME_BASE: Country = {name: 'AT'}; - readonly apiURL: string = 'https://restcountries.com/v3.1/all'; + private readonly HOME_BASE: Country = { name: 'AT' }; + private readonly COUNTRY_INFORMATION_SERVICE_URL: string = 'https://restcountries.com/v3.1/all'; static getCurrent(): RestCountriesAPI { return new RestCountriesAPI(); @@ -28,7 +28,7 @@ export class RestCountriesAPI { } public isInCommonMarket(country: Country) { - let countryDescription = this.getCountry(country); + const countryDescription = this.getCountryDescriptionViaRestCall(country); return countryDescription.then((c) => c?.regionalBlocs?.filter(b => b.acronym === 'EU').length === 1 @@ -36,20 +36,20 @@ export class RestCountriesAPI { } public isInAmericas(country: Country) { - let countryDescription = this.getCountry(country); + const countryDescription = this.getCountryDescriptionViaRestCall(country); return countryDescription.then((c) => c?.region === 'Americas'); } public distanceTo(country: Country) { return Promise.all([ - this.getCountry(this.HOME_BASE), - this.getCountry(country) + this.getCountryDescriptionViaRestCall(this.HOME_BASE), + this.getCountryDescriptionViaRestCall(country) ]).then(bothCountries => { if (!bothCountries || !bothCountries[0] || !bothCountries[1]) { return 0; } - return (this.distBetween(bothCountries[0].latlng[0], bothCountries[0].latlng[1], bothCountries[1].latlng[0], bothCountries[1].latlng[1])/1000).toFixed(0); + return (this.distBetween(bothCountries[0].latlng[0], bothCountries[0].latlng[1], bothCountries[1].latlng[0], bothCountries[1].latlng[1]) / 1000).toFixed(0); }); } @@ -70,24 +70,23 @@ export class RestCountriesAPI { return value * Math.PI / 180; } - private async getCountry(country: Country): Promise { - let data = await this.getAllCountries(); + private async getCountryDescriptionViaRestCall(country: Country): Promise { + const countryDescriptions: RestCountry[] = await this.slowHttpCall(); - let countries: RestCountry[] = JSON.parse(data); + for (let i = 0; i < countryDescriptions.length; i++) { + if (countryDescriptions[i].alpha2Code === country.name) { + return countryDescriptions[i]; + } + } - return countries.filter(c => c.alpha2Code === country.name).at(0); + return null; } - private async getAllCountries(): Promise { + private async slowHttpCall(): Promise { const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); - - try { - await sleep(4000); - let res = await fetch(this.apiURL); - return await res.text(); - } catch (error) { - console.log(error); - } - return ""; + await sleep(1000); // Sleep for 1 second + const response = await fetch(this.COUNTRY_INFORMATION_SERVICE_URL); + const countryDescriptions = JSON.parse(await response.text()); + return countryDescriptions; } } diff --git a/TypeScript/app/d/shipping.cost.ts b/TypeScript/app/d/shipping.cost.ts index deeecb9..e595d6b 100644 --- a/TypeScript/app/d/shipping.cost.ts +++ b/TypeScript/app/d/shipping.cost.ts @@ -1,6 +1,6 @@ -import {Money} from "./money"; -import {Country} from "./country"; -import {RestCountriesAPI} from "./rest-countries-api"; +import { Money } from "./money"; +import { Country } from "./country"; +import { RestCountriesAPI } from "./rest-countries-api"; export enum DeliveryOptions { Standard, @@ -9,26 +9,27 @@ export enum DeliveryOptions { export class ShippingCost { - public async calculate(destination: Country, options: DeliveryOptions): Promise { + public async calculate(country: Country, options: DeliveryOptions): Promise { let cost: Money; - if (await RestCountriesAPI.getCurrent().isInCommonMarket(destination)) { + if (await RestCountriesAPI.getCurrent().isInCommonMarket(country)) { // flat rate in EU - return new Money(5); - } else if (await RestCountriesAPI.getCurrent().isInAmericas(destination)) { + cost = new Money(5); + + } else if (await RestCountriesAPI.getCurrent().isInAmericas(country)) { // US & Canada & South American if (options === DeliveryOptions.Express) { cost = new Money(40); } else { cost = new Money(15); } - return cost; + } else { // other countries, e.g. Asia - const km = await RestCountriesAPI.getCurrent().distanceTo(destination); - return new Money(km).percentage(10); + const km = await RestCountriesAPI.getCurrent().distanceTo(country); + cost = new Money(km).percentage(10); } - // flat rate in EU - return new Money(5); + + return cost; } } diff --git a/TypeScript/test/d/rest-countries-api.test.ts b/TypeScript/test/d/rest-countries-api.test.ts new file mode 100644 index 0000000..828273a --- /dev/null +++ b/TypeScript/test/d/rest-countries-api.test.ts @@ -0,0 +1,36 @@ +import { RestCountriesAPI } from "../../app/d/rest-countries-api"; +import { expect } from "chai"; + +describe('RestCountriesAPITest', () => { + + it('isInAmericas', async () => { + return RestCountriesAPI.getCurrent().isInAmericas({ name: 'US' }) + .then(val => expect(val).to.be.true); + }); + + it('not isInCommonMarket', async () => { + return RestCountriesAPI.getCurrent().isInCommonMarket({ name: 'US' }) + .then(val => expect(val).to.be.false); + }); + + it('distanceTo', async () => { + return RestCountriesAPI.getCurrent().distanceTo({ name: 'US' }) + .then(val => expect(val).to.equal(8284767)); + }); + + it('not isInAmericas', async () => { + return RestCountriesAPI.getCurrent().isInAmericas({ name: 'AT' }) + .then(val => expect(val).to.be.false); + }); + + it('isInCommonMarket', async () => { + return RestCountriesAPI.getCurrent().isInCommonMarket({ name: 'AT' }) + .then(val => expect(val).to.be.true); + }); + + it('no distanceTo', async () => { + return RestCountriesAPI.getCurrent().distanceTo({ name: 'AT' }) + .then(val => expect(val).to.equal(0)); + }); + +}); diff --git a/TypeScript/test/d/shipping-cost.test.ts b/TypeScript/test/d/shipping-cost.test.ts index d2f2091..321a294 100644 --- a/TypeScript/test/d/shipping-cost.test.ts +++ b/TypeScript/test/d/shipping-cost.test.ts @@ -1,28 +1,12 @@ -import {RestCountriesAPI} from "../../app/d/rest-countries-api"; -import {DeliveryOptions, ShippingCost} from "../../app/d/shipping.cost"; +import { ShippingCost } from "../../app/d/shipping.cost"; +import { expect } from "chai"; -describe('ShippingCost Test', () => { +describe('ShippingCost', () => { - it('test isInAmericas', () => { - return RestCountriesAPI.getCurrent().isInAmericas({name: 'US'}) - .then(val => console.log(val)); - }); - - it('test isInCommonMarket', () => { - return RestCountriesAPI.getCurrent().isInCommonMarket({name: 'AT'}) - .then(val => console.log(val)); - }); - - it('test distanceTo', () => { - return RestCountriesAPI.getCurrent().distanceTo({name: 'US'}) - .then(val => console.log(val)); - }); - - it('test ShippingCost', () => { - let shippingCost = new ShippingCost(); + it('test 4', () => { + const shippingCost = new ShippingCost(); - return shippingCost.calculate({name: 'US'}, DeliveryOptions.Express) - .then(val => console.log(val)); + expect(shippingCost).not.to.be.null; }); -}); \ No newline at end of file +});