-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from rolger/typescript_port
feature: first migration to typescript
- Loading branch information
Showing
27 changed files
with
8,806 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
node_modules/ | ||
npm-debug.log | ||
typings | ||
.idea | ||
.iml | ||
src/*.js | ||
test/*.js | ||
*.js.map | ||
tsconfig.tsbuildinfo | ||
|
||
dist/ | ||
coverage/ | ||
.nyc_output/ |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
# Dependency Breaking Katas | ||
|
||
Exercises to practice breaking dependencies in legacy | ||
code to create tests for it. | ||
|
||
## Goal | ||
|
||
We have some legacy code. We need to make changes. | ||
To make changes we need to introduce tests first. | ||
We might have to change some code to enable testing. | ||
We need to introduce so-called Seams (see [Michael | ||
Feathers' Working Effectively with Legacy | ||
Code](https://www.goodreads.com/book/show/44919.Working_Effectively_with_Legacy_Code)). | ||
|
||
Changing code without test is risky, so we want to | ||
|
||
* Only change as little code as possible. | ||
* Rely on automated Refactoring tools as much as possible. | ||
* You must not change the public API of the class. | ||
|
||
### Assignments for Techniques | ||
|
||
* Parametrise Constructor | ||
* Subclass And Override Method | ||
* Extract And Override Call | ||
* Replace Global Reference With Getter | ||
* Extract And Override Factory Method | ||
|
||
Planned | ||
|
||
* Extract Interface | ||
* Adapt Parameter | ||
|
||
### Task | ||
|
||
Each task presents you with a class and some collaborators. | ||
|
||
* Bring this class under test. Make sure to cover all paths in the core logic. | ||
* There is an existing test class with a first test case which might or might not work. | ||
* You cannot change collaborators because they are used by other teams as well. | ||
|
||
### License | ||
|
||
[New BSD License](http://opensource.org/licenses/bsd-license.php), see `license.txt` in repository. | ||
|
||
(This is a copied document - do not edit!) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module type="WEB_MODULE" version="4"> | ||
<component name="NewModuleRootManager" inherit-compiler-output="true"> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$" /> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
</component> | ||
</module> |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
Assignment A | ||
============ | ||
|
||
Goal | ||
---- | ||
|
||
We have some legacy code. We need to make changes. | ||
To make changes we need to introduce tests first. | ||
We might have to change some code to enable testing. | ||
We need to introduce so-called Seams (see Michael | ||
Feathers' Working Effectively with Legacy Code). | ||
Changing code without test is risky, so we want to | ||
|
||
* Only change as little code as possible. | ||
* Rely on automated Refactoring tools as much as possible. | ||
* You must not change the public API of the class. | ||
|
||
Problem Category | ||
---------------- | ||
|
||
The system under test depends on a collaborator with | ||
non deterministic behaviour. The collaborator is | ||
initialised in the constructor. | ||
|
||
Task | ||
---- | ||
|
||
The given code calculates the discount for a purchase in | ||
our online shop. The main logic is in `Discount`. | ||
|
||
* Bring `Discount` under test. Make sure to cover all paths in the core logic. | ||
* There is an existing `DiscountTest` with a first test case which might or might not work. | ||
* You cannot change `MarketingCampaign` because it is used by other teams as well. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import {Money} from "./money"; | ||
import {MarketingCampaign} from "./marketing-campaign"; | ||
|
||
export class Discount { | ||
|
||
marketingCampaign: MarketingCampaign; | ||
|
||
constructor() { | ||
this.marketingCampaign = new MarketingCampaign(); | ||
} | ||
|
||
discountFor(netPrice: Money): Money { | ||
if (this.marketingCampaign.isCrazySalesDay()) { | ||
return netPrice.reduceBy(15); | ||
} | ||
if (netPrice.moreThan(Money.ONE_THOUSAND)) { | ||
return netPrice.reduceBy(10); | ||
} | ||
if (netPrice.moreThan(Money.ONE_HUNDRED) && this.marketingCampaign.isActive()) { | ||
return netPrice.reduceBy(5); | ||
} | ||
return netPrice; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export class MarketingCampaign { | ||
|
||
public isActive(): boolean { | ||
let now: Date = new Date(); | ||
return now.getMilliseconds() % 2 == 0; | ||
} | ||
|
||
public isCrazySalesDay(): boolean { | ||
let now: Date = new Date(); | ||
return now.getDay() === 5; | ||
} | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
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) { | ||
if (typeof value === 'string') { | ||
this.value = Number.parseFloat(value); | ||
} else { | ||
this.value = value; | ||
} | ||
} | ||
|
||
reduceBy(p: number): Money { | ||
// value.multiply(new BigDecimal(100 - p)).divide(new BigDecimal(100)) | ||
return new Money((this.value * (100 - p) / 100).toFixed(2)); | ||
} | ||
|
||
moreThan(other: Money): boolean { | ||
return this.value > other.value; | ||
} | ||
|
||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
Assignment B | ||
============ | ||
|
||
Goal | ||
---- | ||
|
||
We have some legacy code. We need to make changes. | ||
To make changes we need to introduce tests first. | ||
We might have to change some code to enable testing. | ||
We need to introduce so-called Seams (see Michael | ||
Feathers' Working Effectively with Legacy Code). | ||
Changing code without test is risky, so we want to | ||
|
||
* Only change as little code as possible. | ||
* Rely on automated Refactoring tools as much as possible. | ||
* You must not change the public API of the class. | ||
|
||
Problem Category | ||
---------------- | ||
|
||
The system under test contains non deterministic behaviour, | ||
which is located in a few methods. The system under test can | ||
be sub-classed. | ||
|
||
Task | ||
---- | ||
|
||
The given `MarketingCampaign` controls the marketing actions which | ||
run on our online shop. During campaigns we e.g. offer discounts. | ||
|
||
* Bring `MarketingCampaign` under test. Make sure to cover all paths in the core logic. | ||
* There is an existing `MarketingCampaignTest` with a first test case which might or might not work. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
export class MarketingCampaign { | ||
|
||
public isActive(): boolean { | ||
return this.milliseconds() % 2 == 0; | ||
} | ||
|
||
public isCrazySalesDay(): boolean { | ||
return this.dayOfWeek() == 5; | ||
} | ||
|
||
private milliseconds(): number { | ||
let now: Date = new Date(); | ||
return now.getMilliseconds(); | ||
} | ||
|
||
private dayOfWeek(): number { | ||
let date: Date = new Date(); | ||
return date.getDay(); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
Assignment C | ||
============ | ||
|
||
Goal | ||
---- | ||
|
||
We have some legacy code. We need to make changes. | ||
To make changes we need to introduce tests first. | ||
We might have to change some code to enable testing. | ||
We need to introduce so-called Seams (see Michael | ||
Feathers' Working Effectively with Legacy Code). | ||
Changing code without test is risky, so we want to | ||
|
||
* Only change as little code as possible. | ||
* Rely on automated Refactoring tools as much as possible. | ||
* You must not change the public API of the class. | ||
|
||
Problem Category | ||
---------------- | ||
|
||
The system under test depends on a collaborator with | ||
database access. The database is not available in our | ||
test environment. The collaborator is a static call. | ||
|
||
Task | ||
---- | ||
|
||
The given code creates the receipt with the calculated tax | ||
for a purchase in our online shop. The main logic is in `Checkout`. | ||
|
||
* Bring `Checkout` under test. Make sure to cover all paths in the core logic. | ||
* There is an existing `CheckoutTest` with a first test case which might or might not work. | ||
* You cannot change `ReceiptRepository` because it is used by other teams as well. |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import {Money} from "./money"; | ||
import {Receipt} from "./receipt"; | ||
import {ReceiptRepository} from "./receipt-repository"; | ||
|
||
|
||
export class Checkout { | ||
|
||
createReceipt(netAmount: Money): Promise<Error | boolean> { | ||
let tax = netAmount.percentage(20); | ||
let total = netAmount.add(tax); | ||
let receipt: Receipt = new Receipt(netAmount, tax, total); | ||
|
||
return ReceiptRepository.store(receipt); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
export class Money { | ||
|
||
public static readonly ZERO: Money = new Money(0); | ||
public static readonly ONE_THOUSAND: Money = new Money(1000); | ||
public static readonly ONE_HUNDRED: Money = new Money(100); | ||
|
||
value: number; | ||
|
||
constructor(value: number | string) { | ||
if (typeof value === 'string') { | ||
this.value = Number.parseFloat(value); | ||
} else { | ||
this.value = value; | ||
} | ||
} | ||
|
||
add(other: Money): Money { | ||
return new Money(this.value + other.value); | ||
} | ||
|
||
percentage(p: number): Money { | ||
return new Money((this.value * p / 100).toFixed(2)); | ||
} | ||
|
||
moreThan(other: Money): boolean { | ||
return this.value > other.value; | ||
} | ||
|
||
format(): string { | ||
return this.value.toFixed(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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import {Receipt} from "./receipt"; | ||
import {Connection, MysqlError} from "mysql"; | ||
|
||
let mysql = require('mysql'); | ||
|
||
const db: Connection = mysql.createConnection({ | ||
host: 'localhost:3306', | ||
user: 'store', | ||
password: '12345', | ||
database: 'store' | ||
}); | ||
|
||
export class ReceiptRepository { | ||
|
||
static store(receipt: Receipt): Promise<Error | boolean> { | ||
return new Promise((resolve, reject) => { | ||
db.connect((err: MysqlError) => { | ||
if (err) { | ||
reject(err); | ||
} else { | ||
|
||
db.query( | ||
"insert into RECEIPT (AMOUNT, TAX, TOTAL) values(?, ?, ?)", | ||
[receipt.amount.value, receipt.tax.value, receipt.total.value], | ||
(err, results) => { | ||
if (err) { | ||
reject(err); | ||
} | ||
if (!results[0]) { | ||
reject(new Error('Data not inserted?')) | ||
} | ||
resolve(true); | ||
}); | ||
|
||
db.end(); | ||
} | ||
}); | ||
}); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import {Money} from "./money"; | ||
|
||
export class Receipt { | ||
constructor(public amount: Money, public tax: Money, public total:Money) { | ||
this.amount = Money.ZERO; | ||
this.tax = Money.ZERO; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
Assignment D | ||
============ | ||
|
||
Goal | ||
---- | ||
|
||
We have some legacy code. We need to make changes. | ||
To make changes we need to introduce tests first. | ||
We might have to change some code to enable testing. | ||
We need to introduce so-called Seams (see Michael | ||
Feathers' Working Effectively with Legacy Code). | ||
Changing code without test is risky, so we want to | ||
|
||
* Only change as little code as possible. | ||
* Rely on automated Refactoring tools as much as possible. | ||
* You must not change the public API of the class. | ||
|
||
Problem Category | ||
---------------- | ||
|
||
The system under test depends on a collaborator with | ||
slow behaviour due to a HTTP call. It is not guaranteed | ||
that the REST server is available. The collaborator is | ||
a Singleton and called multiple times. | ||
|
||
Task | ||
---- | ||
|
||
The given code calculates the shipping cost for a purchase | ||
depending on the destination in our online shop. The main | ||
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. |
Oops, something went wrong.