Skip to content

Commit

Permalink
bank-account added
Browse files Browse the repository at this point in the history
  • Loading branch information
TheRealOwenRees committed Jan 25, 2024
1 parent 45526ca commit 9b3821b
Show file tree
Hide file tree
Showing 16 changed files with 1,678 additions and 85 deletions.
420 changes: 335 additions & 85 deletions config.json

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions exercises/practice/bank-account/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Instructions

Simulate a bank account supporting opening/closing, withdrawals, and deposits of money.
Watch out for concurrent transactions!

A bank account can be accessed in multiple ways.
Clients can make deposits and withdrawals using the internet, mobile phones, etc.
Shops can charge against the account.

Create an account that can be accessed from multiple threads/processes (terminology depends on your programming language).

It should be possible to close an account; operations against a closed account must fail.
13 changes: 13 additions & 0 deletions exercises/practice/bank-account/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
!.meta

# Protected or generated
.git
.vscode

# When using npm
node_modules/*

# Configuration files
.eslintrc.cjs
babel.config.cjs
jest.config.cjs
38 changes: 38 additions & 0 deletions exercises/practice/bank-account/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module.exports = {
root: true,
parserOptions: {
tsconfigRootDir: __dirname,
project: ['./tsconfig.json'],
},
overrides: [
// Student provided files
{
files: ['*.ts'],
excludedFiles: ['.meta/proof.ci.ts', '.meta/exemplar.ts', '*.test.ts'],
extends: '@exercism/eslint-config-typescript',
},
// Exercism given tests
{
files: ['*.test.ts'],
excludedFiles: ['custom.test.ts'],
env: {
jest: true,
},
extends: '@exercism/eslint-config-typescript/maintainers',
},
// Student provided tests
{
files: ['custom.test.ts'],
env: {
jest: true,
},
extends: '@exercism/eslint-config-typescript',
},
// Exercism provided files
{
files: ['.meta/proof.ci.ts', '.meta/exemplar.ts', '*.test.ts'],
excludedFiles: ['custom.test.ts'],
extends: '@exercism/eslint-config-typescript/maintainers',
},
],
}
17 changes: 17 additions & 0 deletions exercises/practice/bank-account/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"authors": [
"therealowenrees"
],
"files": {
"solution": [
"bank-account.ts"
],
"test": [
"bank-account.test.ts"
],
"example": [
".meta/proof.ci.ts"
]
},
"blurb": "Simulate a bank account supporting opening/closing, withdraws, and deposits of money. Watch out for concurrent transactions!"
}
42 changes: 42 additions & 0 deletions exercises/practice/bank-account/.meta/proof.ci.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
export class ValueError extends Error {
constructor() {
super('Bank account error')
}
}

export class BankAccount {
private _isOpen: boolean
private _balance: number

constructor() {
this._isOpen = false
this._balance = 0
}

open(): void {
if (this._isOpen) throw new ValueError()
this._isOpen = true
}

close(): void {
if (!this._isOpen) throw new ValueError()
this._isOpen = false
this._balance = 0
}

deposit(amount: number): void {
if (!this._isOpen || amount < 0) throw new ValueError()
this._balance += amount
}

withdraw(amount: number): void {
if (!this._isOpen || amount < 0 || amount > this._balance)
throw new ValueError()
this._balance -= amount
}

get balance(): number {
if (!this._isOpen) throw new ValueError()
return this._balance
}
}
41 changes: 41 additions & 0 deletions exercises/practice/bank-account/.meta/solutions/bank-account.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export class ValueError extends Error {
constructor() {
super('Bank account error');
}
}

export class BankAccount {
private _isOpen: boolean
private _balance: number

constructor() {
this._isOpen = false
this._balance = 0
}

open(): void {
if (this._isOpen) throw new ValueError
this._isOpen = true
}

close(): void {
if (!this._isOpen) throw new ValueError
this._isOpen = false
this._balance = 0
}

deposit(amount: number): void {
if (!this._isOpen || amount < 0) throw new ValueError
this._balance += amount
}

withdraw(amount: number): void {
if (!this._isOpen || amount < 0 || amount > this._balance) throw new ValueError
this._balance -= amount
}

get balance(): number {
if (!this._isOpen) throw new ValueError
return this._balance
}
}
61 changes: 61 additions & 0 deletions exercises/practice/bank-account/.meta/tests.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# This is an auto-generated file.
#
# Regenerating this file via `configlet sync` will:
# - Recreate every `description` key/value pair
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
# - Preserve any other key/value pair
#
# As user-added comments (using the # character) will be removed when this file
# is regenerated, comments can be added via a `comment` key.

[983a1528-4ceb-45e5-8257-8ce01aceb5ed]
description = "Newly opened account has zero balance"

[e88d4ec3-c6bf-4752-8e59-5046c44e3ba7]
description = "Single deposit"

[3d9147d4-63f4-4844-8d2b-1fee2e9a2a0d]
description = "Multiple deposits"

[08f1af07-27ae-4b38-aa19-770bde558064]
description = "Withdraw once"

[6f6d242f-8c31-4ac6-8995-a90d42cad59f]
description = "Withdraw twice"

[45161c94-a094-4c77-9cec-998b70429bda]
description = "Can do multiple operations sequentially"

[f9facfaa-d824-486e-8381-48832c4bbffd]
description = "Cannot check balance of closed account"

[7a65ba52-e35c-4fd2-8159-bda2bde6e59c]
description = "Cannot deposit into closed account"

[a0a1835d-faae-4ad4-a6f3-1fcc2121380b]
description = "Cannot deposit into unopened account"

[570dfaa5-0532-4c1f-a7d3-0f65c3265608]
description = "Cannot withdraw from closed account"

[c396d233-1c49-4272-98dc-7f502dbb9470]
description = "Cannot close an account that was not opened"

[c06f534f-bdc2-4a02-a388-1063400684de]
description = "Cannot open an already opened account"

[0722d404-6116-4f92-ba3b-da7f88f1669c]
description = "Reopened account does not retain balance"

[ec42245f-9361-4341-8231-a22e8d19c52f]
description = "Cannot withdraw more than deposited"

[4f381ef8-10ef-4507-8e1d-0631ecc8ee72]
description = "Cannot withdraw negative"

[d45df9ea-1db0-47f3-b18c-d365db49d938]
description = "Cannot deposit negative"

[ba0c1e0b-0f00-416f-8097-a7dfc97871ff]
description = "Can handle concurrent transactions"
874 changes: 874 additions & 0 deletions exercises/practice/bank-account/.yarn/releases/yarn-3.6.4.cjs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions exercises/practice/bank-account/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
yarnPath: .yarn/releases/yarn-3.6.4.cjs
4 changes: 4 additions & 0 deletions exercises/practice/bank-account/babel.config.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
presets: ['@exercism/babel-preset-typescript'],
plugins: [],
}
125 changes: 125 additions & 0 deletions exercises/practice/bank-account/bank-account.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import { BankAccount, ValueError } from './bank-account'

describe('Bank Account', () => {
test('newly opened account has zero balance', () => {
const account = new BankAccount()
account.open()
expect(account.balance).toEqual(0)
})

xit('can deposit money', () => {
const account = new BankAccount()
account.open()
account.deposit(100)
expect(account.balance).toEqual(100)
})

xit('can deposit money sequentially', () => {
const account = new BankAccount()
account.open()
account.deposit(100)
account.deposit(50)
expect(account.balance).toEqual(150)
})

xit('can withdraw money', () => {
const account = new BankAccount()
account.open()
account.deposit(100)
account.withdraw(50)
expect(account.balance).toEqual(50)
})

xit('can withdraw money sequentially', () => {
const account = new BankAccount()
account.open()
account.deposit(100)
account.withdraw(20)
account.withdraw(80)
expect(account.balance).toEqual(0)
})

xit('checking balance of closed account throws error', () => {
const account = new BankAccount()
account.open()
account.close()
expect(() => account.balance).toThrow(ValueError)
})

xit('deposit into closed account throws error', () => {
const account = new BankAccount()
account.open()
account.close()
expect(() => {
account.deposit(50)
}).toThrow(ValueError)
})

xit('withdraw from closed account throws error', () => {
const account = new BankAccount()
account.open()
account.close()
expect(() => {
account.withdraw(50)
}).toThrow(ValueError)
})

xit('close already closed account throws error', () => {
const account = new BankAccount()
expect(() => {
account.close()
}).toThrow(ValueError)
})

xit('open already opened account throws error', () => {
const account = new BankAccount()
account.open()
expect(() => {
account.open()
}).toThrow(ValueError)
})

xit('reopened account does not retain balance', () => {
const account = new BankAccount()
account.open()
account.deposit(50)
account.close()
account.open()
expect(account.balance).toEqual(0)
})

xit('cannot withdraw more than deposited', () => {
const account = new BankAccount()
account.open()
account.deposit(25)
expect(() => {
account.withdraw(50)
}).toThrow(ValueError)
})

xit('cannot withdraw negative amount', () => {
const account = new BankAccount()
account.open()
account.deposit(100)
expect(() => {
account.withdraw(-50)
}).toThrow(ValueError)
})

xit('cannot deposit negative amount', () => {
const account = new BankAccount()
account.open()
expect(() => {
account.deposit(-50)
}).toThrow(ValueError)
})

xit('changing balance directly throws error', () => {
const account = new BankAccount()
account.open()
expect(() => {
account.balance = 100
}).toThrow(Error)
})
})

Loading

0 comments on commit 9b3821b

Please sign in to comment.