-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathnot-pure-chains.test.ts
More file actions
99 lines (87 loc) · 2.39 KB
/
not-pure-chains.test.ts
File metadata and controls
99 lines (87 loc) · 2.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { consume } from "../../src/consumers";
import {
filterAsync,
mapAsync,
notAsync,
peekAsync,
} from "../../src/transformers";
interface UserAccount {
name: string;
cipheredPassword: string;
}
async function* hackedUserService(): AsyncIterable<UserAccount> {
yield {
name: "alice",
cipheredPassword: "smart-hash-123abc",
};
yield {
name: "bob",
cipheredPassword: "smart-hash-456def",
};
yield {
name: "charlie",
cipheredPassword: "smart-hash-789ghi",
};
}
const hackedBankService = (() => {
const accounts: any = {
alice: {
balance: 10_000,
password: "123abc",
},
charlie: {
balance: 0,
password: "a-v3ry-g00d-p4ssw0rd",
},
};
return {
canLoginIn: async (name: string, password: string) =>
accounts[name]?.password === password,
emptyBalance: async (name: string, password: string) =>
accounts[name]?.password === password && accounts[name].balance === 0,
withdrawAccount: async (name: string, password: string, amount: number) => {
if (accounts[name]?.password === password)
accounts[name].balance -= amount;
},
accounts,
};
})();
const passwordDecipherService = async (password: string) =>
password.replace(/smart-hash-/, "");
interface HackedUserAccount {
name: string;
password: string;
}
test("not-pure chains are not the nicest", async () => {
const decipherPasswords = mapAsync(
async ({
name,
cipheredPassword,
}: UserAccount): Promise<HackedUserAccount> => ({
name,
password: await passwordDecipherService(cipheredPassword),
})
);
const filterHackedBankAccounts = filterAsync(
({ name, password }: { name: string; password: string }) =>
hackedBankService.canLoginIn(name, password)
);
const accountHasMoney = filterAsync(
notAsync(({ name, password }: { name: string; password: string }) =>
hackedBankService.emptyBalance(name, password)
)
);
const withdrawUserMoney = peekAsync(
({ name, password }: { name: string; password: string }) =>
hackedBankService.withdrawAccount(name, password, 5_000)
);
await consume(
withdrawUserMoney(
accountHasMoney(
filterHackedBankAccounts(decipherPasswords(hackedUserService()))
)
)
);
expect(hackedBankService.accounts.alice.balance).toEqual(5_000);
expect(hackedBankService.accounts.charlie.balance).toEqual(0);
});