Skip to content

Commit 54e18af

Browse files
committed
refactor: switch to export-based evaluation pattern
- Replace console.log Results output with direct exports - Rewrite tests to import modules directly instead of parsing stdout - Add export instructions with 🐨 and 💰 hints in problem files - Add helpful 🚨 error messages for common mistakes - Fix interface export issue (interfaces are type-only, not runtime values)
1 parent 4cab844 commit 54e18af

File tree

42 files changed

+332
-388
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+332
-388
lines changed

exercises/01.classes/01.problem.class-basics/index.ts

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,5 @@
1919
// cart.addItem(mouse)
2020
// console.log(cart.getTotal())
2121

22-
// 🐨 When you're done, uncomment this:
23-
// const sampleCart = new ShoppingCart()
24-
// const sampleLaptop = new Product('Laptop', 999.99)
25-
// const sampleMouse = new Product('Mouse', 29.99)
26-
// sampleCart.addItem(sampleLaptop)
27-
// sampleCart.addItem(sampleMouse)
28-
// console.log(
29-
// 'Results:',
30-
// JSON.stringify({
31-
// product: {
32-
// name: sampleLaptop.name,
33-
// price: sampleLaptop.price,
34-
// description: sampleLaptop.getDescription(),
35-
// },
36-
// cart: {
37-
// itemsCount: sampleCart.items.length,
38-
// firstItemName: sampleCart.items[0]?.name,
39-
// secondItemName: sampleCart.items[1]?.name,
40-
// total: sampleCart.getTotal(),
41-
// },
42-
// }),
43-
// )
22+
// 🐨 Export your classes so we can verify your work
23+
// 💰 export { Product, ShoppingCart }

exercises/01.classes/01.problem.class-basics/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "exercises_01.classes_01.problem.class-basics",
33
"type": "module",
44
"scripts": {
5-
"start": "node index.ts",
5+
"start": "npx @kentcdodds/log-module@latest ./index.ts",
66
"test": "node --test index.test.ts"
77
}
88
}

exercises/01.classes/01.solution.class-basics/index.test.ts

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,93 @@
11
import assert from 'node:assert/strict'
2-
import { execSync } from 'node:child_process'
32
import { test } from 'node:test'
3+
import * as solution from './index.ts'
44

5-
const output = execSync('npm start --silent', { encoding: 'utf8' })
6-
const jsonLine = output.split('\n').find((line) => line.startsWith('Results:'))
7-
assert.ok(jsonLine, '🚨 Missing "Results:" output line')
8-
const { product, cart, emptyCart } = JSON.parse(
9-
jsonLine.replace('Results:', '').trim(),
10-
)
5+
await test('Product class should be exported', () => {
6+
assert.ok(
7+
'Product' in solution,
8+
'🚨 Make sure you export "Product" - add: export { Product, ShoppingCart }',
9+
)
10+
})
11+
12+
await test('ShoppingCart class should be exported', () => {
13+
assert.ok(
14+
'ShoppingCart' in solution,
15+
'🚨 Make sure you export "ShoppingCart" - add: export { Product, ShoppingCart }',
16+
)
17+
})
1118

1219
await test('Product class should create instances with name and price', () => {
20+
const sampleLaptop = new solution.Product('Laptop', 999.99)
1321
assert.strictEqual(
14-
product.name,
22+
sampleLaptop.name,
1523
'Laptop',
1624
'🚨 Product.name should be "Laptop" - check your class property definition',
1725
)
1826
assert.strictEqual(
19-
product.price,
27+
sampleLaptop.price,
2028
999.99,
2129
'🚨 Product.price should be 999.99 - check your class property definition',
2230
)
2331
})
2432

2533
await test('Product getDescription should return formatted string', () => {
34+
const sampleLaptop = new solution.Product('Laptop', 999.99)
2635
assert.strictEqual(
27-
product.description,
36+
sampleLaptop.getDescription(),
2837
'Product: Laptop - $999.99',
29-
'🚨 getDescription() should return "Product: Mouse - $29.99" - check your method implementation and formatting',
38+
'🚨 getDescription() should return "Product: Laptop - $999.99" - check your method implementation and formatting',
3039
)
3140
})
3241

3342
await test('ShoppingCart should initialize with empty items array', () => {
43+
const emptyCart = new solution.ShoppingCart()
3444
assert.strictEqual(
35-
emptyCart.itemsCount,
45+
emptyCart.items.length,
3646
0,
3747
'🚨 ShoppingCart.items.length should be 0 - check your class property initialization',
3848
)
3949
})
4050

4151
await test('ShoppingCart addItem should add products to cart', () => {
52+
const sampleCart = new solution.ShoppingCart()
53+
const sampleLaptop = new solution.Product('Laptop', 999.99)
54+
const sampleMouse = new solution.Product('Mouse', 29.99)
55+
sampleCart.addItem(sampleLaptop)
56+
const afterFirstAddCount = sampleCart.items.length
57+
sampleCart.addItem(sampleMouse)
58+
4259
assert.strictEqual(
43-
cart.itemsAfterFirstAdd,
60+
afterFirstAddCount,
4461
1,
4562
'🚨 After adding one item, items.length should be 1 - check your addItem method implementation',
4663
)
4764
assert.strictEqual(
48-
cart.firstItemName,
65+
sampleCart.items[0]?.name,
4966
'Laptop',
5067
'🚨 items[0] should be the laptop product - check your addItem method implementation',
5168
)
5269

5370
assert.strictEqual(
54-
cart.itemsCount,
71+
sampleCart.items.length,
5572
2,
5673
'🚨 After adding two items, items.length should be 2 - check your addItem method implementation',
5774
)
5875
assert.strictEqual(
59-
cart.secondItemName,
76+
sampleCart.items[1]?.name,
6077
'Mouse',
6178
'🚨 items[1] should be the mouse product - check your addItem method implementation',
6279
)
6380
})
6481

6582
await test('ShoppingCart getTotal should calculate sum of all item prices', () => {
83+
const sampleCart = new solution.ShoppingCart()
84+
const sampleLaptop = new solution.Product('Laptop', 999.99)
85+
const sampleMouse = new solution.Product('Mouse', 29.99)
86+
sampleCart.addItem(sampleLaptop)
87+
sampleCart.addItem(sampleMouse)
88+
6689
assert.strictEqual(
67-
cart.total,
90+
sampleCart.getTotal(),
6891
1029.98,
6992
'🚨 getTotal() should return 1029.98 (sum of 999.99 + 29.99) - check your method implementation and price calculation',
7093
)

exercises/01.classes/01.solution.class-basics/index.ts

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -41,31 +41,4 @@ cart.addItem(laptop)
4141
cart.addItem(mouse)
4242
console.log(`Cart total: $${cart.getTotal()}`)
4343

44-
const sampleCart = new ShoppingCart()
45-
const emptyCart = new ShoppingCart()
46-
const sampleLaptop = new Product('Laptop', 999.99)
47-
const sampleMouse = new Product('Mouse', 29.99)
48-
sampleCart.addItem(sampleLaptop)
49-
const afterFirstAddCount = sampleCart.items.length
50-
sampleCart.addItem(sampleMouse)
51-
52-
console.log(
53-
'Results:',
54-
JSON.stringify({
55-
product: {
56-
name: sampleLaptop.name,
57-
price: sampleLaptop.price,
58-
description: sampleLaptop.getDescription(),
59-
},
60-
cart: {
61-
itemsCount: sampleCart.items.length,
62-
itemsAfterFirstAdd: afterFirstAddCount,
63-
firstItemName: sampleCart.items[0]?.name,
64-
secondItemName: sampleCart.items[1]?.name,
65-
total: sampleCart.getTotal(),
66-
},
67-
emptyCart: {
68-
itemsCount: emptyCart.items.length,
69-
},
70-
}),
71-
)
44+
export { Product, ShoppingCart }

exercises/01.classes/01.solution.class-basics/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "exercises_01.classes_01.solution.class-basics",
33
"type": "module",
44
"scripts": {
5-
"start": "node index.ts",
5+
"start": "npx @kentcdodds/log-module@latest ./index.ts",
66
"test": "node --test index.test.ts"
77
}
88
}

exercises/01.classes/02.problem.constructors/index.ts

Lines changed: 2 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,5 @@
2626
// const config = new Config()
2727
// const customConfig = new Config('example.com', 8080, true)
2828

29-
// 🐨 When you're done, uncomment this:
30-
// const sampleAccount = new BankAccount('12345')
31-
// sampleAccount.deposit(100)
32-
// sampleAccount.deposit(50)
33-
// console.log(
34-
// 'Results:',
35-
// JSON.stringify({
36-
// user: { name: user.name, email: user.email, role: user.role },
37-
// admin: { name: admin.name, email: admin.email, role: admin.role },
38-
// account: {
39-
// accountNumber: sampleAccount.accountNumber,
40-
// initialBalance: 0,
41-
// balanceAfterFirstDeposit: 100,
42-
// balanceAfterSecondDeposit: 150,
43-
// },
44-
// config: { host: config.host, port: config.port, debug: config.debug },
45-
// customConfig: {
46-
// host: customConfig.host,
47-
// port: customConfig.port,
48-
// debug: customConfig.debug,
49-
// },
50-
// }),
51-
// )
29+
// 🐨 Export your classes so we can verify your work
30+
// 💰 export { User, BankAccount, Config }

exercises/01.classes/02.problem.constructors/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "exercises_01.classes_02.problem.constructors",
33
"type": "module",
44
"scripts": {
5-
"start": "node index.ts",
6-
"test": "node --experimental-transform-types --test index.test.ts"
5+
"start": "npx @kentcdodds/log-module@latest ./index.ts",
6+
"test": "node --test index.test.ts"
77
}
88
}

exercises/01.classes/02.solution.constructors/index.test.ts

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
11
import assert from 'node:assert/strict'
2-
import { execSync } from 'node:child_process'
32
import { test } from 'node:test'
3+
import * as solution from './index.ts'
44

5-
const output = execSync('npm start --silent', { encoding: 'utf8' })
6-
const jsonLine = output.split('\n').find((line) => line.startsWith('Results:'))
7-
assert.ok(jsonLine, '🚨 Missing "Results:" output line')
8-
const { user, admin, account, config, customConfig } = JSON.parse(
9-
jsonLine.replace('Results:', '').trim(),
10-
)
5+
await test('User class should be exported', () => {
6+
assert.ok(
7+
'User' in solution,
8+
'🚨 Make sure you export "User" - add: export { User, BankAccount, Config }',
9+
)
10+
})
11+
12+
await test('BankAccount class should be exported', () => {
13+
assert.ok(
14+
'BankAccount' in solution,
15+
'🚨 Make sure you export "BankAccount" - add: export { User, BankAccount, Config }',
16+
)
17+
})
18+
19+
await test('Config class should be exported', () => {
20+
assert.ok(
21+
'Config' in solution,
22+
'🚨 Make sure you export "Config" - add: export { User, BankAccount, Config }',
23+
)
24+
})
1125

1226
await test('User constructor should set name, email, and default role', () => {
27+
const user = new solution.User('Alice', '[email protected]')
1328
assert.strictEqual(
1429
user.name,
1530
'Alice',
@@ -28,6 +43,7 @@ await test('User constructor should set name, email, and default role', () => {
2843
})
2944

3045
await test('User constructor should accept custom role', () => {
46+
const admin = new solution.User('Bob', '[email protected]', 'admin')
3147
assert.strictEqual(
3248
admin.name,
3349
'Bob',
@@ -46,32 +62,39 @@ await test('User constructor should accept custom role', () => {
4662
})
4763

4864
await test('BankAccount constructor should set accountNumber and default balance', () => {
65+
const sampleAccount = new solution.BankAccount('12345')
4966
assert.strictEqual(
50-
account.accountNumber,
67+
sampleAccount.accountNumber,
5168
'12345',
5269
'🚨 BankAccount.accountNumber should be "12345" - check your constructor parameter assignment',
5370
)
5471
assert.strictEqual(
55-
account.initialBalance,
72+
sampleAccount.getBalance(),
5673
0,
5774
'🚨 BankAccount.getBalance() should return 0 initially - check your constructor initialization',
5875
)
5976
})
6077

6178
await test('BankAccount deposit should increase balance', () => {
79+
const sampleAccount = new solution.BankAccount('12345')
80+
sampleAccount.deposit(100)
81+
const balanceAfterFirstDeposit = sampleAccount.getBalance()
82+
sampleAccount.deposit(50)
83+
6284
assert.strictEqual(
63-
account.balanceAfterFirstDeposit,
85+
balanceAfterFirstDeposit,
6486
100,
6587
'🚨 After depositing 100, getBalance() should return 100 - check your deposit method implementation',
6688
)
6789
assert.strictEqual(
68-
account.balanceAfterSecondDeposit,
90+
sampleAccount.getBalance(),
6991
150,
7092
'🚨 After depositing another 50, getBalance() should return 150 - check your deposit method accumulates correctly',
7193
)
7294
})
7395

7496
await test('Config constructor should use default values', () => {
97+
const config = new solution.Config()
7598
assert.strictEqual(
7699
config.host,
77100
'localhost',
@@ -90,6 +113,7 @@ await test('Config constructor should use default values', () => {
90113
})
91114

92115
await test('Config constructor should accept custom values', () => {
116+
const customConfig = new solution.Config('example.com', 8080, true)
93117
assert.strictEqual(
94118
customConfig.host,
95119
'example.com',

exercises/01.classes/02.solution.constructors/index.ts

Lines changed: 1 addition & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -60,27 +60,4 @@ const customConfig = new Config('example.com', 8080, true)
6060
console.log(`Default config: ${config.host}:${config.port}`)
6161
console.log(`Custom config: ${customConfig.host}:${customConfig.port}`)
6262

63-
const sampleAccount = new BankAccount('12345')
64-
sampleAccount.deposit(100)
65-
const balanceAfterFirstDeposit = sampleAccount.getBalance()
66-
sampleAccount.deposit(50)
67-
68-
console.log(
69-
'Results:',
70-
JSON.stringify({
71-
user: { name: user.name, email: user.email, role: user.role },
72-
admin: { name: admin.name, email: admin.email, role: admin.role },
73-
account: {
74-
accountNumber: sampleAccount.accountNumber,
75-
initialBalance: 0,
76-
balanceAfterFirstDeposit,
77-
balanceAfterSecondDeposit: sampleAccount.getBalance(),
78-
},
79-
config: { host: config.host, port: config.port, debug: config.debug },
80-
customConfig: {
81-
host: customConfig.host,
82-
port: customConfig.port,
83-
debug: customConfig.debug,
84-
},
85-
}),
86-
)
63+
export { User, BankAccount, Config }

exercises/01.classes/02.solution.constructors/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "exercises_01.classes_02.solution.constructors",
33
"type": "module",
44
"scripts": {
5-
"start": "node index.ts",
6-
"test": "node --experimental-transform-types --test index.test.ts"
5+
"start": "npx @kentcdodds/log-module@latest ./index.ts",
6+
"test": "node --test index.test.ts"
77
}
88
}

0 commit comments

Comments
 (0)