mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
Compare commits
5093 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
273ba0381f | ||
|
|
63a05d86e8 | ||
|
|
283e115d0a | ||
|
|
b513ebba8e | ||
|
|
e324cea7b9 | ||
|
|
c3cda91a2d | ||
|
|
bb9f611629 | ||
|
|
6cc8e62b15 | ||
|
|
5a44b76adb | ||
|
|
109d6bc617 | ||
|
|
7249ff6107 | ||
|
|
406830fa13 | ||
|
|
a6a3278443 | ||
|
|
9fd8531529 | ||
|
|
c687976796 | ||
|
|
ae511929f7 | ||
|
|
e78e756206 | ||
|
|
2e9e0dac1a | ||
|
|
bff97712e2 | ||
|
|
78bc25cce0 | ||
|
|
a2e829417d | ||
|
|
9902413daf | ||
|
|
06a35f4a73 | ||
|
|
e2a46157b9 | ||
|
|
c4913a94c4 | ||
|
|
d6e04c3ae8 | ||
|
|
5b17ef5217 | ||
|
|
8edeedc32c | ||
|
|
543dbc9e50 | ||
|
|
3710f4297b | ||
|
|
91d6ba4da8 | ||
|
|
fbfa3c1abe | ||
|
|
d13d7bef0c | ||
|
|
510f5d7190 | ||
|
|
595b98d4b7 | ||
|
|
c696107aeb | ||
|
|
632722cd7b | ||
|
|
60c264ea49 | ||
|
|
10ce92264d | ||
|
|
2e5c7aa6bc | ||
|
|
1e7e2c5b51 | ||
|
|
46790ce3fe | ||
|
|
7bd891f8f0 | ||
|
|
1ae16acbac | ||
|
|
2281fb7f61 | ||
|
|
89e8db6c6e | ||
|
|
11300692e5 | ||
|
|
a31161c6d8 | ||
|
|
edd85f8ec0 | ||
|
|
0d420604dd | ||
|
|
777f5666e2 | ||
|
|
e7bded641f | ||
|
|
6f0dfbe038 | ||
|
|
0e92eeb50e | ||
|
|
50b6cb879a | ||
|
|
739ebde6a8 | ||
|
|
24ef74f16d | ||
|
|
9e0a57ca5b | ||
|
|
feaebb6f0f | ||
|
|
9a45759414 | ||
|
|
14c5a0447b | ||
|
|
7793e03d82 | ||
|
|
f422573fcc | ||
|
|
516109ecd3 | ||
|
|
31d32b16a5 | ||
|
|
435c1bd6e2 | ||
|
|
6d5ebf3f58 | ||
|
|
b97036b447 | ||
|
|
d7ef3cb896 | ||
|
|
2218eefa67 | ||
|
|
666d33d767 | ||
|
|
3f4f83d354 | ||
|
|
3dea547559 | ||
|
|
0e9c6acb84 | ||
|
|
1b6881673e | ||
|
|
f069b33b60 | ||
|
|
c0a86e31da | ||
|
|
7b95778efe | ||
|
|
ef8a102d0a | ||
|
|
95448de3ed | ||
|
|
0a574762c7 | ||
|
|
59b1440990 | ||
|
|
98d6729d4b | ||
|
|
135a0bbe5c | ||
|
|
c3f579931d | ||
|
|
21c51e81d2 | ||
|
|
e6538c95ad | ||
|
|
0e63e87f9b | ||
|
|
1e900ec775 | ||
|
|
5ff30874dd | ||
|
|
94550006c4 | ||
|
|
202636ce72 | ||
|
|
cae8c6f622 | ||
|
|
0e03c4377f | ||
|
|
7497ea1262 | ||
|
|
d68bb34f6f | ||
|
|
732a6f4942 | ||
|
|
70fb896ae1 | ||
|
|
034eae6722 | ||
|
|
3472949bf0 | ||
|
|
c333b8ca30 | ||
|
|
17e3fbdabf | ||
|
|
30c5c9dfaf | ||
|
|
585d1ee38a | ||
|
|
3255afb487 | ||
|
|
9f75648b50 | ||
|
|
50406f8984 | ||
|
|
f24c7ebc5f | ||
|
|
75dcecfab0 | ||
|
|
34c603ce53 | ||
|
|
7785a73876 | ||
|
|
cfa8f731f2 | ||
|
|
5ecd05c7b3 | ||
|
|
4ec95c2f1c | ||
|
|
9e4413b02e | ||
|
|
38d0d689b3 | ||
|
|
799c5e9e4e | ||
|
|
b98dffda8f | ||
|
|
d816d841a8 | ||
|
|
1730e02dc3 | ||
|
|
53737d2f3c | ||
|
|
932dc3f9f6 | ||
|
|
567fdb6a36 | ||
|
|
3e323b929d | ||
|
|
a53fb126ac | ||
|
|
ec2c17bc21 | ||
|
|
3894f31c2c | ||
|
|
342b96801a | ||
|
|
36f1dfe2e0 | ||
|
|
f90951add1 | ||
|
|
7d65c45833 | ||
|
|
3629235a00 | ||
|
|
09ff7744dc | ||
|
|
1fa9d59634 | ||
|
|
ccec9dbc70 | ||
|
|
a49dbad913 | ||
|
|
4f0497158b | ||
|
|
4757d158a8 | ||
|
|
4bbd371a42 | ||
|
|
10b4b877de | ||
|
|
3bd030c397 | ||
|
|
7c408808c9 | ||
|
|
39dcaa8fc4 | ||
|
|
04cdd584a2 | ||
|
|
2693487f81 | ||
|
|
d73dce8804 | ||
|
|
cf333e8c15 | ||
|
|
5aea28611b | ||
|
|
c58ccf0a66 | ||
|
|
d5c870eb9d | ||
|
|
a41b00e0be | ||
|
|
383ee7e577 | ||
|
|
b3b1f887ef | ||
|
|
b6089f5d28 | ||
|
|
2d7d5cad39 | ||
|
|
cb06833882 | ||
|
|
cf3ab86cec | ||
|
|
efd3d18484 | ||
|
|
e6baaa6184 | ||
|
|
81c943ecda | ||
|
|
587a4f479c | ||
|
|
5638152121 | ||
|
|
81fc744270 | ||
|
|
2437b9e028 | ||
|
|
d148cac10e | ||
|
|
af8c9e3cc3 | ||
|
|
b64c71c307 | ||
|
|
2d60d8fcc1 | ||
|
|
814221997e | ||
|
|
5e112b6f59 | ||
|
|
6b253c30b2 | ||
|
|
b5b0c1efa7 | ||
|
|
5dce6f81af | ||
|
|
6ff186d7de | ||
|
|
801a1cab1a | ||
|
|
737539e3a8 | ||
|
|
2992f868ef | ||
|
|
e718ef80dc | ||
|
|
220a441422 | ||
|
|
8440eb513a | ||
|
|
09004fd7db | ||
|
|
e9fb2bf677 | ||
|
|
81261e2413 | ||
|
|
2c7b51dc00 | ||
|
|
47447badc1 | ||
|
|
1233a2347d | ||
|
|
b0cec6f668 | ||
|
|
05e25d51ec | ||
|
|
81c27836c2 | ||
|
|
24aa1ec1b3 | ||
|
|
6c7bc84ff4 | ||
|
|
bc1d139cca | ||
|
|
c1afef18f3 | ||
|
|
f46ff6237b | ||
|
|
fd94e8037d | ||
|
|
b95bf75dce | ||
|
|
b08b3aa3b1 | ||
|
|
5ed931243e | ||
|
|
f5ab48c8af | ||
|
|
75202f4ff8 | ||
|
|
3c679674d5 | ||
|
|
6f7921691c | ||
|
|
13ba136c66 | ||
|
|
abd80af816 | ||
|
|
aac927e6ea | ||
|
|
f7e0d7d698 | ||
|
|
eb633bae3a | ||
|
|
76a0b5e3e2 | ||
|
|
0679525905 | ||
|
|
3396c7bca4 | ||
|
|
5031ce3936 | ||
|
|
8b774b47e2 | ||
|
|
f0e7a398fa | ||
|
|
72c3f23c67 | ||
|
|
33c01b611e | ||
|
|
7cc2e6953b | ||
|
|
1284d4ab80 | ||
|
|
cd83f01132 | ||
|
|
3b4480fa8b | ||
|
|
a9f8fbbff5 | ||
|
|
e37b055e24 | ||
|
|
8eeda0e647 | ||
|
|
c28b47e231 | ||
|
|
ab989107a5 | ||
|
|
268fe93dd9 | ||
|
|
e154fb05ea | ||
|
|
fb14fe587b | ||
|
|
e72a17ce32 | ||
|
|
6c11409e7e | ||
|
|
f43db71b01 | ||
|
|
dc3611474f | ||
|
|
5c5a306f7f | ||
|
|
024d9fb5ac | ||
|
|
6fb480042f | ||
|
|
acc1f8624e | ||
|
|
0b97853a57 | ||
|
|
8408b55e08 | ||
|
|
e49d9f7eab | ||
|
|
6202bd78f3 | ||
|
|
a2a5916e09 | ||
|
|
3f52e42661 | ||
|
|
224032d0c2 | ||
|
|
4dece2e58a | ||
|
|
7eb85d4454 | ||
|
|
bd750e6f97 | ||
|
|
ee0d4d29e1 | ||
|
|
10d2ea7c0a | ||
|
|
0ab76d53ec | ||
|
|
3dea0a5f67 | ||
|
|
41c2e04cfa | ||
|
|
d8183feb07 | ||
|
|
e49fe2bca8 | ||
|
|
67664a2816 | ||
|
|
eefbe00aec | ||
|
|
be67d5f120 | ||
|
|
fa1fe694cf | ||
|
|
9f681c0c09 | ||
|
|
18dde2849e | ||
|
|
5678774de0 | ||
|
|
f5370e1384 | ||
|
|
934d7cb104 | ||
|
|
33b201147d | ||
|
|
abe2006e15 | ||
|
|
81b5cb386d | ||
|
|
c713dd6c87 | ||
|
|
eda5c490b7 | ||
|
|
b6bc9e1257 | ||
|
|
123ffd8886 | ||
|
|
9a2c09c6e8 | ||
|
|
5b5fdde9a2 | ||
|
|
0cc50d70da | ||
|
|
c79ecddee4 | ||
|
|
e929edbd53 | ||
|
|
8de7a1ec70 | ||
|
|
0b6ae4d225 | ||
|
|
c69bb8bb2b | ||
|
|
e8dda6f946 | ||
|
|
3daebfc0c1 | ||
|
|
d5fcbb97c3 | ||
|
|
97555e7849 | ||
|
|
7eb799d2a6 | ||
|
|
d06a85a3b6 | ||
|
|
f616eadccf | ||
|
|
b69d6c193b | ||
|
|
d12908778e | ||
|
|
95c42f3266 | ||
|
|
597e6de682 | ||
|
|
406141a4f1 | ||
|
|
0db7fe63b0 | ||
|
|
e5a43ef5b6 | ||
|
|
4d9a9c9ac2 | ||
|
|
3cc1f6b994 | ||
|
|
4322361269 | ||
|
|
44d3651aa8 | ||
|
|
03423f32c8 | ||
|
|
bf8c950a8a | ||
|
|
f16ae734cc | ||
|
|
91196dca39 | ||
|
|
ea36ff5011 | ||
|
|
dad418140b | ||
|
|
d5f8877768 | ||
|
|
95f2dfa8ac | ||
|
|
d60b14c686 | ||
|
|
fabcd7b8f4 | ||
|
|
045880c234 | ||
|
|
d2071102c5 | ||
|
|
864bc8c7f9 | ||
|
|
b63b861b8a | ||
|
|
23effbb3ec | ||
|
|
c0a87c834c | ||
|
|
4d02213260 | ||
|
|
46118964ea | ||
|
|
ca52c588fd | ||
|
|
b9905e10de | ||
|
|
7ea08af177 | ||
|
|
fa59aff6d5 | ||
|
|
c90e3bedb1 | ||
|
|
62cf565a09 | ||
|
|
4503361877 | ||
|
|
f2bc7ef3ed | ||
|
|
f9505e42c4 | ||
|
|
d340df758e | ||
|
|
741ecf0955 | ||
|
|
90ab2e468e | ||
|
|
360b9d7730 | ||
|
|
bb698dbe9d | ||
|
|
5e120a7328 | ||
|
|
206daba741 | ||
|
|
79e86e8b76 | ||
|
|
398c17c75a | ||
|
|
49adc95170 | ||
|
|
2b71bd1178 | ||
|
|
c53938bc0a | ||
|
|
718827d757 | ||
|
|
b4c87e7e10 | ||
|
|
20dd0e9b2d | ||
|
|
397e2d207e | ||
|
|
29f7b6cb74 | ||
|
|
a004b55e8c | ||
|
|
221d8f0697 | ||
|
|
e7a243ab7f | ||
|
|
ce1ffe2070 | ||
|
|
32e2419b67 | ||
|
|
5f7079e526 | ||
|
|
4ffeae11e2 | ||
|
|
7621e31d38 | ||
|
|
c00c751127 | ||
|
|
a09f550b52 | ||
|
|
0aeb1cfa97 | ||
|
|
46da7e45b9 | ||
|
|
83bf448bdd | ||
|
|
5ab15fb812 | ||
|
|
0dc70f3e42 | ||
|
|
5bc86a75bc | ||
|
|
51d3df9282 | ||
|
|
31925ea099 | ||
|
|
a56e6540e8 | ||
|
|
03bccb4cb4 | ||
|
|
bba9b7b6ec | ||
|
|
5b8ea6e4b0 | ||
|
|
91676d802c | ||
|
|
395d343f69 | ||
|
|
201993ff08 | ||
|
|
f9499904f3 | ||
|
|
0a152474a2 | ||
|
|
8dc522e054 | ||
|
|
eb8209d575 | ||
|
|
96b3ac7435 | ||
|
|
42d7113896 | ||
|
|
7f19786053 | ||
|
|
52b121a9f4 | ||
|
|
d191a8223e | ||
|
|
b371b43a86 | ||
|
|
c243f384a5 | ||
|
|
e10f8d759c | ||
|
|
977e5b8cb6 | ||
|
|
b68f95a7e7 | ||
|
|
e30b01de23 | ||
|
|
68f87db33e | ||
|
|
f2bfa462a0 | ||
|
|
adffcf5229 | ||
|
|
a4f37cbcfa | ||
|
|
18d8328a9c | ||
|
|
a466578ebf | ||
|
|
c92f8833e2 | ||
|
|
2f46c58028 | ||
|
|
a1c24e346c | ||
|
|
fb7fb62a0e | ||
|
|
7378ee1a32 | ||
|
|
0bee5b4365 | ||
|
|
47bfd6f539 | ||
|
|
1b92cb7f86 | ||
|
|
2931d47d05 | ||
|
|
7668a54648 | ||
|
|
aa0aaf7c10 | ||
|
|
4b80da96ab | ||
|
|
396fa19d7b | ||
|
|
4cd235a08e | ||
|
|
edd21956c5 | ||
|
|
f842156253 | ||
|
|
ce0ce0f229 | ||
|
|
ae2e9219c3 | ||
|
|
146b374ca8 | ||
|
|
9264676407 | ||
|
|
eb74460fcf | ||
|
|
16ed582052 | ||
|
|
a7ddb81ad1 | ||
|
|
d09f3870b1 | ||
|
|
9a8e249964 | ||
|
|
c63d9cf0b9 | ||
|
|
f6648f80ec | ||
|
|
250bff7ef3 | ||
|
|
fa0b925aa9 | ||
|
|
28fe2949f2 | ||
|
|
d7f46216e9 | ||
|
|
3f0d82a427 | ||
|
|
d2811c9fba | ||
|
|
028e26ef59 | ||
|
|
4086332857 | ||
|
|
1eebfccf14 | ||
|
|
f1127f917d | ||
|
|
6cc8700bb9 | ||
|
|
3cabcd5cf9 | ||
|
|
c5aaeb67b5 | ||
|
|
47fcd54d1c | ||
|
|
5dd5cd8ae1 | ||
|
|
8ab18160a5 | ||
|
|
b70b697f3f | ||
|
|
48eb35e20d | ||
|
|
4fd899133f | ||
|
|
3b134cf8b5 | ||
|
|
86bc538601 | ||
|
|
fb00fbc850 | ||
|
|
309f9fcfa1 | ||
|
|
253aa63980 | ||
|
|
93dea13f20 | ||
|
|
3d3d1718b7 | ||
|
|
90c2a5d51f | ||
|
|
8846a229d8 | ||
|
|
acf0591adc | ||
|
|
95bee47826 | ||
|
|
b701976356 | ||
|
|
2b61941e34 | ||
|
|
1526ffa3af | ||
|
|
bb4227e537 | ||
|
|
778691405d | ||
|
|
cb7d3b91c6 | ||
|
|
fd8cf16336 | ||
|
|
2403cf222f | ||
|
|
20152dd8a6 | ||
|
|
b459207b7a | ||
|
|
8b009509c8 | ||
|
|
c456891a11 | ||
|
|
6b044d8086 | ||
|
|
3162de84ed | ||
|
|
641768240a | ||
|
|
8b7ade4b9c | ||
|
|
c7db9394c8 | ||
|
|
513e63329b | ||
|
|
cfd104385d | ||
|
|
2d9641eecf | ||
|
|
65a78125b2 | ||
|
|
28572ba4d3 | ||
|
|
28a603ca1e | ||
|
|
b9fa303f7f | ||
|
|
756dde90ab | ||
|
|
c2a396167e | ||
|
|
c1fd207723 | ||
|
|
8f1fc0a164 | ||
|
|
538ec3c744 | ||
|
|
6fed13bf12 | ||
|
|
104cc7c900 | ||
|
|
8fa699a92e | ||
|
|
1ab7059830 | ||
|
|
377b2613db | ||
|
|
bc7b0a9bdb | ||
|
|
8665a351db | ||
|
|
dd02bf8b8d | ||
|
|
487c423eef | ||
|
|
87bcfa729c | ||
|
|
0332e8c671 | ||
|
|
7264354ce6 | ||
|
|
bde3315994 | ||
|
|
7ecd08b0d8 | ||
|
|
93feb382ca | ||
|
|
186d9b3798 | ||
|
|
1f3e44819d | ||
|
|
4b942f2f45 | ||
|
|
7214cd7179 | ||
|
|
90c11b5c04 | ||
|
|
4007339d26 | ||
|
|
8bc43443a7 | ||
|
|
a389dc702b | ||
|
|
1b39fa37e0 | ||
|
|
bfa18f72fa | ||
|
|
82c2ec0c43 | ||
|
|
3810d088b5 | ||
|
|
7b34b096fe | ||
|
|
831b0bd2d1 | ||
|
|
5875057282 | ||
|
|
b78df8df2a | ||
|
|
7fa3d08e61 | ||
|
|
549303a34c | ||
|
|
9d2cbae115 | ||
|
|
d1a76922c5 | ||
|
|
648889d2d2 | ||
|
|
984e566fe2 | ||
|
|
145296ee10 | ||
|
|
91b91ca96f | ||
|
|
5ea1e9d6d5 | ||
|
|
78f83fe103 | ||
|
|
1b0ee6a757 | ||
|
|
c185853405 | ||
|
|
f50b8bceb6 | ||
|
|
559a10603a | ||
|
|
defe38daaa | ||
|
|
6acdaf0603 | ||
|
|
e9991fc995 | ||
|
|
7ad14174d7 | ||
|
|
a638387dd4 | ||
|
|
3818d0e607 | ||
|
|
3ce4f8da3a | ||
|
|
9d272a1b19 | ||
|
|
3b9224b4da | ||
|
|
b254152746 | ||
|
|
a2d796476e | ||
|
|
898e744767 | ||
|
|
9ef9c5b3de | ||
|
|
b734eeb252 | ||
|
|
92d69d9053 | ||
|
|
4879c49476 | ||
|
|
e81ea15bb0 | ||
|
|
647f174b53 | ||
|
|
d79e6a7606 | ||
|
|
3fd3916ef9 | ||
|
|
b9b73d44c2 | ||
|
|
afa7c2030c | ||
|
|
f668a7a629 | ||
|
|
958fb43ac2 | ||
|
|
9ef8f592ba | ||
|
|
e6feae6c68 | ||
|
|
9dc5810eaa | ||
|
|
c960d6d96a | ||
|
|
45d95d7b45 | ||
|
|
3d1c32a5b4 | ||
|
|
6a67580c33 | ||
|
|
dbafa0a473 | ||
|
|
d348e73b55 | ||
|
|
3f3c1bd6e3 | ||
|
|
1a3f907c62 | ||
|
|
4f8027c6f7 | ||
|
|
86cd2a976b | ||
|
|
52a935bf09 | ||
|
|
ea7c3c4a5b | ||
|
|
9639d98dc3 | ||
|
|
3bfc16b6a8 | ||
|
|
1e54619e81 | ||
|
|
fc4ac98246 | ||
|
|
534e3ee98f | ||
|
|
9b8b8f020d | ||
|
|
aea7fb8069 | ||
|
|
b933633cc0 | ||
|
|
a822eb521d | ||
|
|
b6bb19538f | ||
|
|
c0a1f86801 | ||
|
|
439d79c677 | ||
|
|
b6ee0f118e | ||
|
|
ed037ca6d7 | ||
|
|
58f6239cb2 | ||
|
|
5e7bfcb591 | ||
|
|
03cd99c43c | ||
|
|
dc1742aca6 | ||
|
|
a23142cc3f | ||
|
|
de47319b00 | ||
|
|
c9a2549018 | ||
|
|
966253f7b6 | ||
|
|
b0ce7fb3cf | ||
|
|
f1f85a6563 | ||
|
|
c10ee5e0a8 | ||
|
|
7e86d3128c | ||
|
|
4f3da0ea2e | ||
|
|
406c7d8c6b | ||
|
|
809f1192f4 | ||
|
|
ff280d27f1 | ||
|
|
c566eb95a2 | ||
|
|
393d80600c | ||
|
|
1e44165d18 | ||
|
|
03f4774810 | ||
|
|
b64e0446a3 | ||
|
|
e51cab2418 | ||
|
|
f533d106c1 | ||
|
|
2557691053 | ||
|
|
5f53f95b5d | ||
|
|
2c71574072 | ||
|
|
45d38494f2 | ||
|
|
5c03d0d14c | ||
|
|
8404294f56 | ||
|
|
7f519bb71f | ||
|
|
7a5995002d | ||
|
|
ba8fe8e830 | ||
|
|
949a5b19cc | ||
|
|
5a68a00f38 | ||
|
|
d52d91852a | ||
|
|
b8b39e1ebd | ||
|
|
e795e63d02 | ||
|
|
27dc58a90f | ||
|
|
d4679353af | ||
|
|
73a53c8829 | ||
|
|
eb51f78f8c | ||
|
|
8667443e64 | ||
|
|
0650472551 | ||
|
|
7653ea683a | ||
|
|
d633d2f424 | ||
|
|
98ec370545 | ||
|
|
51b9579d6e | ||
|
|
af42791fa2 | ||
|
|
f7e9a88575 | ||
|
|
331ac4787e | ||
|
|
4ac2e0aa49 | ||
|
|
0cb10c206a | ||
|
|
5fd031f518 | ||
|
|
48c204a7b0 | ||
|
|
e61fc1c84e | ||
|
|
fb64381af9 | ||
|
|
84954f1919 | ||
|
|
cdabe516eb | ||
|
|
e5ddb2cef9 | ||
|
|
963185b927 | ||
|
|
f7ef6a207e | ||
|
|
8088d14340 | ||
|
|
f710b782a3 | ||
|
|
b13921f9aa | ||
|
|
522191052a | ||
|
|
e9e8844342 | ||
|
|
ccbf7b24cf | ||
|
|
57f1417d4c | ||
|
|
d5318e6e88 | ||
|
|
978e3fc610 | ||
|
|
dcb5eef814 | ||
|
|
518ad838e7 | ||
|
|
ba6ced577e | ||
|
|
138253e728 | ||
|
|
ffd299962b | ||
|
|
354a147155 | ||
|
|
a623017325 | ||
|
|
654bd80abd | ||
|
|
3249591351 | ||
|
|
40f934d7a6 | ||
|
|
53717dcc46 | ||
|
|
f16a00fe2e | ||
|
|
ab1af0ce28 | ||
|
|
be444bbbc4 | ||
|
|
e161872604 | ||
|
|
e21fa015bf | ||
|
|
fb3275d89f | ||
|
|
f42e4ffc71 | ||
|
|
7b15c190d3 | ||
|
|
73c2d27620 | ||
|
|
288db125ce | ||
|
|
0effaae435 | ||
|
|
a71f1dd3c6 | ||
|
|
c08843d587 | ||
|
|
44094cd4f4 | ||
|
|
a4bd9d518c | ||
|
|
a739a6e24a | ||
|
|
955b52d54b | ||
|
|
004293008c | ||
|
|
9f26a0b512 | ||
|
|
b16f95a4ba | ||
|
|
c079531d2e | ||
|
|
773f2dc074 | ||
|
|
64d783179b | ||
|
|
3dafd6c277 | ||
|
|
fb2fdb10b2 | ||
|
|
50dedf84d5 | ||
|
|
d7b96a7dca | ||
|
|
1d1acdf7c8 | ||
|
|
440bc76f08 | ||
|
|
d2a598dbf5 | ||
|
|
931f9dab6f | ||
|
|
10ec2af398 | ||
|
|
46382ef89f | ||
|
|
c4116feda4 | ||
|
|
4c18342cf4 | ||
|
|
92f103c1dd | ||
|
|
8c9374e00a | ||
|
|
870f3d2ef9 | ||
|
|
d75b3596aa | ||
|
|
c388d84f57 | ||
|
|
782f6c9655 | ||
|
|
078d12f2a1 | ||
|
|
271e1aa26a | ||
|
|
c9c11c7ff7 | ||
|
|
75da4667b7 | ||
|
|
a2591f7f77 | ||
|
|
72b4e8bd39 | ||
|
|
740b0bc3b1 | ||
|
|
3e48b15db0 | ||
|
|
f1b8a22cc8 | ||
|
|
02b75fcb68 | ||
|
|
9b2541975f | ||
|
|
d3ff9a5b7c | ||
|
|
75acf7d132 | ||
|
|
d6a9430c20 | ||
|
|
5a89720f59 | ||
|
|
bee7133e81 | ||
|
|
8522f88d66 | ||
|
|
10ecc5c75d | ||
|
|
cdd722c975 | ||
|
|
7fd9b258aa | ||
|
|
5368d398fe | ||
|
|
30cc8c8711 | ||
|
|
f7d1fea2af | ||
|
|
ee5674bb6d | ||
|
|
5e1fa61c55 | ||
|
|
92f968f933 | ||
|
|
9eabd75864 | ||
|
|
df121e68b4 | ||
|
|
be0721fa5d | ||
|
|
d670872d73 | ||
|
|
68eb9162a9 | ||
|
|
a65ce23a10 | ||
|
|
bea9bca891 | ||
|
|
9f2c6fe8cc | ||
|
|
07e4276190 | ||
|
|
3db15c168d | ||
|
|
7e9f66ec61 | ||
|
|
c7ce4ec4e3 | ||
|
|
ad32aed204 | ||
|
|
2df9235516 | ||
|
|
a0efb0b9a4 | ||
|
|
a244741640 | ||
|
|
e3f5360a7f | ||
|
|
c280bae14f | ||
|
|
e99671ba81 | ||
|
|
73338462e5 | ||
|
|
1912e69375 | ||
|
|
60a3789e9c | ||
|
|
a89bc5a5ce | ||
|
|
08f3126f46 | ||
|
|
53e746146b | ||
|
|
1e7cc0d655 | ||
|
|
b37a81b297 | ||
|
|
6aec8118f2 | ||
|
|
756732803f | ||
|
|
a6b8abb9ce | ||
|
|
38feb54237 | ||
|
|
ee828de086 | ||
|
|
bc82638fea | ||
|
|
edb6f58f66 | ||
|
|
23b9a6e7bf | ||
|
|
0b3c6058e2 | ||
|
|
cb6572980e | ||
|
|
78e5bbb9dc | ||
|
|
12b52b3e79 | ||
|
|
e226749388 | ||
|
|
001cd0cdcd | ||
|
|
c3806348a0 | ||
|
|
c6a8d80d45 | ||
|
|
2babacd15a | ||
|
|
456ab29a34 | ||
|
|
1de201841a | ||
|
|
a5586fd4ea | ||
|
|
a14ac78957 | ||
|
|
1193ede1ca | ||
|
|
8ad75a1773 | ||
|
|
9ea1b44e64 | ||
|
|
b92ef7922d | ||
|
|
3d6eff639f | ||
|
|
011e761d7f | ||
|
|
a2fdb687a1 | ||
|
|
ff846e0cc1 | ||
|
|
df0ad0d9f1 | ||
|
|
716d1a6cba | ||
|
|
3e7468177d | ||
|
|
d4113e6715 | ||
|
|
7f7ce06d0e | ||
|
|
7cfea596fd | ||
|
|
7eae5d0f6e | ||
|
|
a390658ad9 | ||
|
|
ecc403cbbc | ||
|
|
e870ca856c | ||
|
|
e7b8fec063 | ||
|
|
7767878c4c | ||
|
|
63de20fe36 | ||
|
|
6114a9a8ed | ||
|
|
d5514ca0cd | ||
|
|
8cf0565211 | ||
|
|
32246b1d69 | ||
|
|
418dbf09ec | ||
|
|
a198d09b71 | ||
|
|
f3bb0e7b90 | ||
|
|
b3917e19a2 | ||
|
|
e7d8b7454f | ||
|
|
4d4660eed9 | ||
|
|
b80e47672d | ||
|
|
3b370841cc | ||
|
|
7ec2a9a0a5 | ||
|
|
e340a376ef | ||
|
|
a2709afc5c | ||
|
|
9c7ed95f23 | ||
|
|
524f1f99cb | ||
|
|
2ac6d7f2bb | ||
|
|
6b3fd9efae | ||
|
|
d99daa6538 | ||
|
|
13e0bba379 | ||
|
|
ed7c5bc537 | ||
|
|
03b7968b99 | ||
|
|
274d64246b | ||
|
|
4450053fd3 | ||
|
|
8c321f18e1 | ||
|
|
e015807edc | ||
|
|
4ebcd2f214 | ||
|
|
67cd8b7a61 | ||
|
|
0a802ca73b | ||
|
|
097f37bfbc | ||
|
|
524e42980a | ||
|
|
34eebc9406 | ||
|
|
65f20c232c | ||
|
|
d742fdae86 | ||
|
|
397e2baf6c | ||
|
|
4b1d951083 | ||
|
|
ab65a5a975 | ||
|
|
9947cbf47b | ||
|
|
f781ba0c6a | ||
|
|
e3c605a7a9 | ||
|
|
849e6761b8 | ||
|
|
407ef36b70 | ||
|
|
fef5ceb36d | ||
|
|
2e22f556d8 | ||
|
|
95b833402f | ||
|
|
c0e7418e7c | ||
|
|
4d72ef1efe | ||
|
|
a00bce399f | ||
|
|
2b8658b233 | ||
|
|
fc2784450b | ||
|
|
896d9bd3ae | ||
|
|
9199096f69 | ||
|
|
bdb2694734 | ||
|
|
98ab3cd3d0 | ||
|
|
22f7d3f9f4 | ||
|
|
7f27dafe32 | ||
|
|
37a1e6d4b5 | ||
|
|
91d5473bf2 | ||
|
|
b883cccb30 | ||
|
|
2ca7b3ba5f | ||
|
|
faada7ae7b | ||
|
|
3910fb778f | ||
|
|
4577d063cc | ||
|
|
1f5c70166e | ||
|
|
f920f9f08d | ||
|
|
e6272e88e6 | ||
|
|
4be24abf7f | ||
|
|
85cc05a144 | ||
|
|
7f726c4e2a | ||
|
|
5c86ffd2ac | ||
|
|
257444b640 | ||
|
|
c61d453de4 | ||
|
|
4b88b18e78 | ||
|
|
1125894e7a | ||
|
|
e8894360fa | ||
|
|
168c071ac3 | ||
|
|
d6dd67951e | ||
|
|
c7e4470a60 | ||
|
|
cb6789504a | ||
|
|
314664c4e2 | ||
|
|
58794f806c | ||
|
|
6a470a6448 | ||
|
|
27bf1713a0 | ||
|
|
c1e428dd3e | ||
|
|
661e5b50f8 | ||
|
|
749c2cf600 | ||
|
|
153e9e01bc | ||
|
|
c1797cc215 | ||
|
|
00eb31cd88 | ||
|
|
bd4b1e485b | ||
|
|
387eacf5ff | ||
|
|
5d00e79e0b | ||
|
|
3aac6a785d | ||
|
|
3506256dff | ||
|
|
5c49ab32e5 | ||
|
|
f128209c3a | ||
|
|
4a4254847a | ||
|
|
d21697367c | ||
|
|
1ceaab2788 | ||
|
|
0c56f20f55 | ||
|
|
261339c7e9 | ||
|
|
1d1335fed5 | ||
|
|
c9b5a53be3 | ||
|
|
11a037aeec | ||
|
|
0743bb5f54 | ||
|
|
9fe5163d86 | ||
|
|
acd107b1a2 | ||
|
|
1ff96df224 | ||
|
|
fb537c46d4 | ||
|
|
a588b454ae | ||
|
|
0f145800fa | ||
|
|
44dfa72f16 | ||
|
|
19152f498c | ||
|
|
056a61c9fe | ||
|
|
a0cfc5d267 | ||
|
|
eb6dbf0c67 | ||
|
|
af2083120e | ||
|
|
95d4c0e992 | ||
|
|
b14f67685a | ||
|
|
b82fa04aec | ||
|
|
93d1e8604a | ||
|
|
53d32dbcc2 | ||
|
|
da43d91b5a | ||
|
|
0694ab0777 | ||
|
|
207940426d | ||
|
|
58a204ed56 | ||
|
|
f68a2719f4 | ||
|
|
4311b019f4 | ||
|
|
c1b7ce0bcc | ||
|
|
fe0ca5403c | ||
|
|
c5c33ebfeb | ||
|
|
2c24843e4d | ||
|
|
b0e17e572c | ||
|
|
7cd5727ccc | ||
|
|
d02bafc7a6 | ||
|
|
ca4bdad32a | ||
|
|
4fab7f9180 | ||
|
|
224f54c676 | ||
|
|
fbc1dbb443 | ||
|
|
4da4e532c5 | ||
|
|
a16447faa2 | ||
|
|
a883b26dda | ||
|
|
b9937ee6ca | ||
|
|
40ed1d5841 | ||
|
|
0d3b86d06b | ||
|
|
f8464d6f23 | ||
|
|
d2995e3b6c | ||
|
|
eda37027d5 | ||
|
|
11f9e5cfa4 | ||
|
|
a59a02a6a7 | ||
|
|
26db867bd5 | ||
|
|
18a92cbaca | ||
|
|
62ac151847 | ||
|
|
0b3628e085 | ||
|
|
ffb23e7f34 | ||
|
|
678d861e22 | ||
|
|
652e08ebbe | ||
|
|
95672569c5 | ||
|
|
c9bedc9315 | ||
|
|
dbaeb39564 | ||
|
|
1e9801b0d4 | ||
|
|
eed82f2b6e | ||
|
|
a0f1545421 | ||
|
|
a69909ff23 | ||
|
|
65c99d3fbd | ||
|
|
687094fec0 | ||
|
|
757debaecc | ||
|
|
6d5dda80ee | ||
|
|
b9d9e965d5 | ||
|
|
e845df2a10 | ||
|
|
93cfc0e15d | ||
|
|
7a35bc2340 | ||
|
|
dc7eebb8ae | ||
|
|
1dfc967900 | ||
|
|
bb5217948d | ||
|
|
c2269711c5 | ||
|
|
e707b99860 | ||
|
|
ec43241ccc | ||
|
|
c45436dcf4 | ||
|
|
d41c3ee72b | ||
|
|
0058d0aa56 | ||
|
|
868638f031 | ||
|
|
a8250f17c3 | ||
|
|
c3bbc7e31c | ||
|
|
5d5565b832 | ||
|
|
5da0ff61b2 | ||
|
|
79efa87d39 | ||
|
|
a56981bc70 | ||
|
|
24f30bf18f | ||
|
|
0fa843fd78 | ||
|
|
aecee331a4 | ||
|
|
c1b7cc6d65 | ||
|
|
b8ddfa6537 | ||
|
|
fd4bd631e5 | ||
|
|
96b8901cde | ||
|
|
124033d122 | ||
|
|
cbb292b828 | ||
|
|
22b5fc2452 | ||
|
|
d549a314bc | ||
|
|
f32fe71dbc | ||
|
|
169cf14fa6 | ||
|
|
3befe007fd | ||
|
|
6d84bafa2e | ||
|
|
f3badc0ad4 | ||
|
|
df9887b629 | ||
|
|
cbecf5b954 | ||
|
|
040cccebe2 | ||
|
|
efffdf54c3 | ||
|
|
c3cb0c8968 | ||
|
|
d676c67b50 | ||
|
|
9316170c89 | ||
|
|
9101614d35 | ||
|
|
7312b2859d | ||
|
|
bf7d99ccba | ||
|
|
fb0d588cbf | ||
|
|
8e7bd6323a | ||
|
|
8bebd1933d | ||
|
|
2429b2c027 | ||
|
|
769820792f | ||
|
|
36f39b5023 | ||
|
|
bb675ee040 | ||
|
|
9b4aff7a3f | ||
|
|
e312d71286 | ||
|
|
a397c686b8 | ||
|
|
9b92005810 | ||
|
|
d4e0c8c3bb | ||
|
|
ae1ec9aaa2 | ||
|
|
e811bb9213 | ||
|
|
7de5d90c82 | ||
|
|
bf5265c15b | ||
|
|
49b111a0e9 | ||
|
|
85964d9f17 | ||
|
|
4f9075fa77 | ||
|
|
0856c9005c | ||
|
|
31d8bccfcf | ||
|
|
9213e3d3ef | ||
|
|
3665079cc9 | ||
|
|
44881e521c | ||
|
|
c136d8050b | ||
|
|
a5cc04b46f | ||
|
|
a9a8b6314b | ||
|
|
5c7be3bcfc | ||
|
|
e3893198af | ||
|
|
6a4e6dc5a1 | ||
|
|
643916f733 | ||
|
|
e964851d53 | ||
|
|
79e495dc14 | ||
|
|
13326879f0 | ||
|
|
293a871db4 | ||
|
|
4c9dc6350d | ||
|
|
4c54afdc55 | ||
|
|
d60841b040 | ||
|
|
7e640f47a5 | ||
|
|
f3d1b273f1 | ||
|
|
e80f5b85e9 | ||
|
|
1b5725caee | ||
|
|
820e8f8323 | ||
|
|
30672e52bb | ||
|
|
ac9796f50d | ||
|
|
66b7b4cad0 | ||
|
|
f417b9cc73 | ||
|
|
a304d4643c | ||
|
|
8386e5a2b5 | ||
|
|
27f57b96c0 | ||
|
|
d9a049d523 | ||
|
|
f53f724b04 | ||
|
|
a41105656a | ||
|
|
54269abfd1 | ||
|
|
e812ff1337 | ||
|
|
ae28f8f239 | ||
|
|
470f261dc0 | ||
|
|
80cfda23b6 | ||
|
|
5321c4d52b | ||
|
|
0466912f3e | ||
|
|
3d3932e657 | ||
|
|
d63117a17a | ||
|
|
ba06a72326 | ||
|
|
2671f6ca61 | ||
|
|
8dddfcbc92 | ||
|
|
ebc5793f36 | ||
|
|
4946221651 | ||
|
|
de9817a97f | ||
|
|
1218c4f385 | ||
|
|
e9cee62d03 | ||
|
|
fa7cf37eab | ||
|
|
b9ecb7556f | ||
|
|
661b38e1e6 | ||
|
|
769f4ba589 | ||
|
|
6118253ebf | ||
|
|
0f7f717330 | ||
|
|
0b16f1eb97 | ||
|
|
e733894c02 | ||
|
|
c47dcfbe27 | ||
|
|
8ae008ec9d | ||
|
|
45ef0c78a3 | ||
|
|
3ac46f239e | ||
|
|
1e106f7ada | ||
|
|
09738b2dd7 | ||
|
|
dc67a0b0fc | ||
|
|
1258bbc770 | ||
|
|
5960318a60 | ||
|
|
d4faf758f4 | ||
|
|
f88216b9a0 | ||
|
|
e21d648588 | ||
|
|
dbcbdc9bbc | ||
|
|
c5d16e8381 | ||
|
|
ac1aa6f3b1 | ||
|
|
866c222c74 | ||
|
|
06843477cb | ||
|
|
9a7a6fc6ab | ||
|
|
4986da415f | ||
|
|
cdbd20b794 | ||
|
|
49567ade65 | ||
|
|
4d857449d2 | ||
|
|
dc03621a14 | ||
|
|
b83cca17e2 | ||
|
|
343afffd40 | ||
|
|
163eac9511 | ||
|
|
167bfcb0b3 | ||
|
|
f0f94eb84c | ||
|
|
7123c9ca12 | ||
|
|
41e12d8e54 | ||
|
|
473ab14ae6 | ||
|
|
127ffd451c | ||
|
|
32bb43b66f | ||
|
|
765f5acbcc | ||
|
|
8ac137f22d | ||
|
|
10bbf6b157 | ||
|
|
390dc0605b | ||
|
|
6fda9f0691 | ||
|
|
0a1c5830d2 | ||
|
|
33efa2316d | ||
|
|
b3de9374a7 | ||
|
|
1d869e8d2b | ||
|
|
56156dd5ff | ||
|
|
35c9f55c41 | ||
|
|
e70e3559eb | ||
|
|
5957439475 | ||
|
|
322ed552ed | ||
|
|
bf848d5ef8 | ||
|
|
285057a9df | ||
|
|
4de62ffa55 | ||
|
|
f97fde1387 | ||
|
|
8a5bba625c | ||
|
|
108a209ac8 | ||
|
|
8390a4aba9 | ||
|
|
9740416e56 | ||
|
|
8cc82642f9 | ||
|
|
5f4804f4cf | ||
|
|
24dbee5d3d | ||
|
|
298f84d25e | ||
|
|
182c66f0a9 | ||
|
|
fd11c34646 | ||
|
|
6bcc7388bb | ||
|
|
60da0c0082 | ||
|
|
2b2b48bec4 | ||
|
|
d579f79399 | ||
|
|
bf85df68b3 | ||
|
|
e6e7ec49df | ||
|
|
e7801e1222 | ||
|
|
3327254022 | ||
|
|
d53d09e358 | ||
|
|
34c02ac391 | ||
|
|
cf4eb0c9cd | ||
|
|
ee6220b1fe | ||
|
|
a264638726 | ||
|
|
3e6a10a57d | ||
|
|
5258816770 | ||
|
|
fb4457f9a1 | ||
|
|
627a74038c | ||
|
|
54c297e898 | ||
|
|
a4d7201f7d | ||
|
|
b04cf69b90 | ||
|
|
ea654f0b8d | ||
|
|
9b16aaf9e4 | ||
|
|
87672de761 | ||
|
|
171a8def6d | ||
|
|
f09179f4cd | ||
|
|
03f62068b3 | ||
|
|
828b4230e3 | ||
|
|
2b23e5d472 | ||
|
|
17dbe70460 | ||
|
|
587c3a0647 | ||
|
|
83f0879b11 | ||
|
|
212b741828 | ||
|
|
ee81b608f9 | ||
|
|
ad17080ee8 | ||
|
|
6a8611c348 | ||
|
|
3ba3610b21 | ||
|
|
8deed23e01 | ||
|
|
356106263b | ||
|
|
0566244b61 | ||
|
|
17d76b4e6f | ||
|
|
9c3490f275 | ||
|
|
b1b6499d7c | ||
|
|
a36a74091f | ||
|
|
4dfbd676af | ||
|
|
f72f8b3e39 | ||
|
|
45cc6880f9 | ||
|
|
17281cd3b1 | ||
|
|
332b452b56 | ||
|
|
c647515186 | ||
|
|
6faf0ed9b9 | ||
|
|
fad024d9bb | ||
|
|
67718df278 | ||
|
|
273c3283c2 | ||
|
|
aa7306ebd1 | ||
|
|
56cb173ad5 | ||
|
|
174f0a9393 | ||
|
|
a1dbc1a6fb | ||
|
|
d9de2ee0bc | ||
|
|
cf1e0eda27 | ||
|
|
ccc82e5a61 | ||
|
|
0859f939dd | ||
|
|
519c133c0c | ||
|
|
9f62860821 | ||
|
|
238ed1ac2c | ||
|
|
cd5903b358 | ||
|
|
f78125c4fb | ||
|
|
6394241b9f | ||
|
|
d4dfc9bbab | ||
|
|
cf668be964 | ||
|
|
6ef443d724 | ||
|
|
75af217864 | ||
|
|
7a7343c3c8 | ||
|
|
18bfa8f562 | ||
|
|
a76a0815a0 | ||
|
|
332f384a65 | ||
|
|
3c5e1216c8 | ||
|
|
c7c11a1c1e | ||
|
|
0dd993c1d0 | ||
|
|
c977e9b59c | ||
|
|
81055b5500 | ||
|
|
c8df446846 | ||
|
|
97ac4621b9 | ||
|
|
9346c474cf | ||
|
|
d9a55965d3 | ||
|
|
50306343a8 | ||
|
|
08d7457620 | ||
|
|
b80a382d2f | ||
|
|
ab066bb441 | ||
|
|
4a64260d6e | ||
|
|
9390077007 | ||
|
|
baf5386e34 | ||
|
|
86e72b2f7f | ||
|
|
70bc02b12e | ||
|
|
6bce8b0195 | ||
|
|
dd4afb1d0a | ||
|
|
95493fe157 | ||
|
|
42b9ef3956 | ||
|
|
97ee7b7a7a | ||
|
|
230860f773 | ||
|
|
5f7f6d975e | ||
|
|
e7c95fdcc1 | ||
|
|
933367a685 | ||
|
|
4857307533 | ||
|
|
1ee50e42ca | ||
|
|
5bbc108331 | ||
|
|
11d62516d9 | ||
|
|
ef714a8bfc | ||
|
|
c6b8441a79 | ||
|
|
200ad86575 | ||
|
|
54fe2f260f | ||
|
|
e056cf743d | ||
|
|
8dbc747928 | ||
|
|
969b37e4e9 | ||
|
|
79a111668e | ||
|
|
9c90e3110b | ||
|
|
59237fb9c6 | ||
|
|
fc3705f019 | ||
|
|
15adbc0823 | ||
|
|
ca6472f5f2 | ||
|
|
de38322f34 | ||
|
|
ed45d30639 | ||
|
|
f99fc6f15f | ||
|
|
56aaa082da | ||
|
|
0aaa2f20bd | ||
|
|
bac589e3ec | ||
|
|
1dc7b02a3c | ||
|
|
83965afe68 | ||
|
|
0e9b110023 | ||
|
|
44f01a77fd | ||
|
|
58552b7a50 | ||
|
|
ddf3feac51 | ||
|
|
c2d59fcee1 | ||
|
|
ee3b2592aa | ||
|
|
ed79dfb220 | ||
|
|
6fbb942ad9 | ||
|
|
94a9340ee3 | ||
|
|
ef6d2b7d2b | ||
|
|
7f0b603f60 | ||
|
|
04ec31ea5c | ||
|
|
d1ff36c44a | ||
|
|
d703443469 | ||
|
|
5455a02c4d | ||
|
|
4bbb186f63 | ||
|
|
b62e8bf976 | ||
|
|
7ccc4fe33a | ||
|
|
b52d1cf1e2 | ||
|
|
6ee9db0eb8 | ||
|
|
36ac2a5bfb | ||
|
|
e1841c652a | ||
|
|
6fc2c88482 | ||
|
|
b8a13a5ba4 | ||
|
|
d36623c1fb | ||
|
|
06ab88556c | ||
|
|
b552790035 | ||
|
|
6610dd22df | ||
|
|
04dddf92d8 | ||
|
|
bedd9c97c2 | ||
|
|
81c859ba31 | ||
|
|
041e662e07 | ||
|
|
65c7c66b50 | ||
|
|
287f2762f9 | ||
|
|
3750e94ff5 | ||
|
|
e127d60345 | ||
|
|
5189298884 | ||
|
|
5a9c370b29 | ||
|
|
ec4f370f29 | ||
|
|
da194dd88d | ||
|
|
91e6b86eb3 | ||
|
|
550e2d59b4 | ||
|
|
80b7ef08c8 | ||
|
|
7c9ddf0c3f | ||
|
|
9abdb1d47b | ||
|
|
a5171dd9b4 | ||
|
|
4e7c04efbe | ||
|
|
d3c66dc750 | ||
|
|
7e14357902 | ||
|
|
92f6c2448f | ||
|
|
b05ebe8bdf | ||
|
|
0b62390a54 | ||
|
|
8c9b5f2a18 | ||
|
|
960894c329 | ||
|
|
a5786ecccf | ||
|
|
33a83928e7 | ||
|
|
149c6271b3 | ||
|
|
031d23df0c | ||
|
|
30134bf3b5 | ||
|
|
7907150f17 | ||
|
|
e5f9639d1e | ||
|
|
47bad16b54 | ||
|
|
efa944ef8c | ||
|
|
68d4cfff16 | ||
|
|
c9c6c4c5ea | ||
|
|
792b3a1267 | ||
|
|
5b64cf6925 | ||
|
|
097878b4b2 | ||
|
|
32eca9aabf | ||
|
|
7a27432885 | ||
|
|
92e4249eec | ||
|
|
6fac0aa0f5 | ||
|
|
cd2ede5ce8 | ||
|
|
ac407375ab | ||
|
|
1730effc55 | ||
|
|
21c063ac53 | ||
|
|
2ba2ef9617 | ||
|
|
cfe2424cff | ||
|
|
397fe2a0c8 | ||
|
|
e846cc532c | ||
|
|
d273f99940 | ||
|
|
f0763c2b67 | ||
|
|
48d6293ab6 | ||
|
|
0e270595df | ||
|
|
db6770159e | ||
|
|
e6bf1ed6f7 | ||
|
|
996dd11e24 | ||
|
|
4ea1f20022 | ||
|
|
a56cfc5688 | ||
|
|
d71d05374f | ||
|
|
99b82b24d0 | ||
|
|
5cfe624e25 | ||
|
|
62066e04e3 | ||
|
|
5478c014f1 | ||
|
|
aea3147454 | ||
|
|
e466de4d0e | ||
|
|
0de3cf72b8 | ||
|
|
41fa97994e | ||
|
|
d03a563e0d | ||
|
|
0f89c0b112 | ||
|
|
07ae096af2 | ||
|
|
11e4d482f4 | ||
|
|
f959e3b869 | ||
|
|
ec19bfb556 | ||
|
|
fa4edf9845 | ||
|
|
ab52430846 | ||
|
|
6045869260 | ||
|
|
c08a598658 | ||
|
|
340483bf7f | ||
|
|
87395e0ec4 | ||
|
|
694194dd01 | ||
|
|
aa6935820d | ||
|
|
57c038dca6 | ||
|
|
fe69b1419f | ||
|
|
0cf7365755 | ||
|
|
7e96f776ff | ||
|
|
e5ce3d46de | ||
|
|
f097cb3c3a | ||
|
|
23aea7b794 | ||
|
|
c2839fdc29 | ||
|
|
3fbd64338c | ||
|
|
36a2917b17 | ||
|
|
9f3fc43791 | ||
|
|
4774d2d1fd | ||
|
|
91de8a5a8f | ||
|
|
652005264b | ||
|
|
98967410cb | ||
|
|
55b2e3f1ff | ||
|
|
cf8ddc98af | ||
|
|
f259fa85a5 | ||
|
|
5ea6c7739f | ||
|
|
eac071af9d | ||
|
|
2b0f424af6 | ||
|
|
fcbfd28025 | ||
|
|
37982fe416 | ||
|
|
6824c85820 | ||
|
|
bd9f76222a | ||
|
|
349e771f74 | ||
|
|
83c2993cef | ||
|
|
dbb91fa140 | ||
|
|
849ca6803d | ||
|
|
f41288f441 | ||
|
|
9e974d5c30 | ||
|
|
62d25ee917 | ||
|
|
652a5dd27d | ||
|
|
1051bfa661 | ||
|
|
3a3c481e3b | ||
|
|
9642c58d94 | ||
|
|
72d37ab218 | ||
|
|
a2047f9498 | ||
|
|
22a94130f2 | ||
|
|
6a907ff0c2 | ||
|
|
11e0ca29d4 | ||
|
|
47cd4ef790 | ||
|
|
25572a9d57 | ||
|
|
02b94e5672 | ||
|
|
23790fefd6 | ||
|
|
3c8e4a24c6 | ||
|
|
0f754055ab | ||
|
|
ac7c2612b2 | ||
|
|
7b54ff2046 | ||
|
|
c7743ffdbe | ||
|
|
7a604d39bd | ||
|
|
7c67f8bba1 | ||
|
|
6f2ca41eb6 | ||
|
|
b26ac16201 | ||
|
|
71b7ba70d1 | ||
|
|
96bd62e0cc | ||
|
|
c2ce598d0f | ||
|
|
cf56069804 | ||
|
|
7834b535d6 | ||
|
|
4b440199a2 | ||
|
|
4facfa5c7a | ||
|
|
99ab247c06 | ||
|
|
5cf12fced5 | ||
|
|
5abc92308a | ||
|
|
ed50ca5b53 | ||
|
|
3e8eb1a6eb | ||
|
|
d360c584c1 | ||
|
|
55482bf28a | ||
|
|
bcf5b4c1b2 | ||
|
|
7098e28532 | ||
|
|
ab8aa2e1ae | ||
|
|
97fc9a8b37 | ||
|
|
5f91a4561b | ||
|
|
b5dd56f187 | ||
|
|
819f0b7d7e | ||
|
|
16399d4512 | ||
|
|
86df184463 | ||
|
|
a4a2d66b85 | ||
|
|
1fb972cf2a | ||
|
|
f1ab0e3449 | ||
|
|
5032646090 | ||
|
|
2facce9633 | ||
|
|
bce50b991e | ||
|
|
bd1a5ef046 | ||
|
|
47e9b4b587 | ||
|
|
676e6127cd | ||
|
|
7b192a4e14 | ||
|
|
e3239ed0b3 | ||
|
|
1423454191 | ||
|
|
285b6367ed | ||
|
|
2907403f82 | ||
|
|
9a735639d4 | ||
|
|
375e3c4636 | ||
|
|
ab3d7078bf | ||
|
|
3b191b917b | ||
|
|
4be129917a | ||
|
|
507f508497 | ||
|
|
4b063b3493 | ||
|
|
8e457a20bc | ||
|
|
b9716cf2a3 | ||
|
|
b05a4ab83a | ||
|
|
ca75eb651d | ||
|
|
a6329fd3c0 | ||
|
|
89e33e984b | ||
|
|
40c0b85a10 | ||
|
|
7cdb199855 | ||
|
|
8c165dc17f | ||
|
|
43fe21a87d | ||
|
|
4b7559f2ec | ||
|
|
9e026034d7 | ||
|
|
9466ccb12a | ||
|
|
f53f314f0b | ||
|
|
9b53a3a052 | ||
|
|
7f8a95646a | ||
|
|
88d452a9fa | ||
|
|
ee2e1412d6 | ||
|
|
f2ea6af1c3 | ||
|
|
76bd5d7518 | ||
|
|
70626ccb79 | ||
|
|
124fca6d1f | ||
|
|
37154cc1ef | ||
|
|
9f42ad5746 | ||
|
|
94c19c8724 | ||
|
|
c3dd9a5f14 | ||
|
|
8f2a6acb7b | ||
|
|
821817fc89 | ||
|
|
0f3097590f | ||
|
|
20826fff54 | ||
|
|
9067e1d8d1 | ||
|
|
dbf983e287 | ||
|
|
f81043133a | ||
|
|
cab9b0bd1e | ||
|
|
d9b42016dc | ||
|
|
5ee5a23b29 | ||
|
|
a1f33d93c1 | ||
|
|
1f9a19c37a | ||
|
|
9e9d371a3f | ||
|
|
b97136a606 | ||
|
|
f1df463a07 | ||
|
|
e59c335cac | ||
|
|
a9280edf97 | ||
|
|
68eca70a31 | ||
|
|
dd68c35295 | ||
|
|
57530af792 | ||
|
|
4947fa91ef | ||
|
|
c605cc77d5 | ||
|
|
6fe6b681ac | ||
|
|
08884af624 | ||
|
|
2adfbb5169 | ||
|
|
831c3c4fa4 | ||
|
|
df87b51e63 | ||
|
|
a17fceac39 | ||
|
|
f6e05a27d8 | ||
|
|
19cb4ee7a4 | ||
|
|
8d4f853432 | ||
|
|
76eaac5d31 | ||
|
|
5c02943ab3 | ||
|
|
09a38e2dcd | ||
|
|
4a772953dd | ||
|
|
be544e09cf | ||
|
|
8a817980db | ||
|
|
1dbfbe5d5f | ||
|
|
53ed0dc12d | ||
|
|
1bbff65f5d | ||
|
|
8e5e9ab517 | ||
|
|
c2d37932e1 | ||
|
|
7e7bbd4591 | ||
|
|
6d2d3c4c3b | ||
|
|
a1ba7f9e5f | ||
|
|
b89949e361 | ||
|
|
72ad111198 | ||
|
|
00b4e9a9b4 | ||
|
|
a460fe12a1 | ||
|
|
7e4fdcd9a3 | ||
|
|
0f4d06b4d4 | ||
|
|
bfbf6edc87 | ||
|
|
5027e2f03a | ||
|
|
70ea05c0ca | ||
|
|
5e9d9abe10 | ||
|
|
128495dd91 | ||
|
|
314a8c0741 | ||
|
|
8c6ca6f8f7 | ||
|
|
421bb3b701 | ||
|
|
a8e9ef49f4 | ||
|
|
2474ad8d1d | ||
|
|
dd58ac01ed | ||
|
|
fd4fc377a1 | ||
|
|
3b31cec3e7 | ||
|
|
28fc95dd1f | ||
|
|
d7dc51980a | ||
|
|
1fd1f08f33 | ||
|
|
f43ec50369 | ||
|
|
d4b6b5744d | ||
|
|
3ae9ddf0f9 | ||
|
|
4a61e5cbdb | ||
|
|
44b031af15 | ||
|
|
ad197f85de | ||
|
|
e7c2990b79 | ||
|
|
21aa33c862 | ||
|
|
3f8cd143b6 | ||
|
|
5d25fec242 | ||
|
|
8aec9f3f25 | ||
|
|
81d14cbecc | ||
|
|
6f1f4cc576 | ||
|
|
f81be0a075 | ||
|
|
2aa57404f2 | ||
|
|
d43cb4b097 | ||
|
|
7d69100d2d | ||
|
|
c04a975dba | ||
|
|
59f920445c | ||
|
|
72425b243b | ||
|
|
8af777fac4 | ||
|
|
510d94b21c | ||
|
|
476cfec461 | ||
|
|
642869ffed | ||
|
|
4e6a552689 | ||
|
|
707581f103 | ||
|
|
ef68d43acb | ||
|
|
50f15f7539 | ||
|
|
9f2ae92236 | ||
|
|
854f14a014 | ||
|
|
cdeef6aae0 | ||
|
|
5000a56620 | ||
|
|
e5438a7c37 | ||
|
|
ed984a0642 | ||
|
|
077c88b778 | ||
|
|
2077b0a35f | ||
|
|
8cbffd7c11 | ||
|
|
3bc3038c2f | ||
|
|
ee3c54ecd0 | ||
|
|
89b10a8ccf | ||
|
|
31d702c550 | ||
|
|
a5f98cb46b | ||
|
|
b88156a672 | ||
|
|
311a53e4ce | ||
|
|
bd55bb88b9 | ||
|
|
7461c5ee1f | ||
|
|
6daf5b6afa | ||
|
|
32c9678513 | ||
|
|
2f74296de6 | ||
|
|
2d32d53075 | ||
|
|
9fa389bb99 | ||
|
|
c9151306da | ||
|
|
5d11777dd8 | ||
|
|
eab9ced72f | ||
|
|
929a72be79 | ||
|
|
c62c8d338e | ||
|
|
524af22cb0 | ||
|
|
b7f891ce39 | ||
|
|
178a20c6d4 | ||
|
|
83e13ae782 | ||
|
|
dc654b89fb | ||
|
|
bee2e084ba | ||
|
|
9ea3f9fd80 | ||
|
|
5d78740f6f | ||
|
|
9cda942dea | ||
|
|
2b728114a2 | ||
|
|
6f1ab140a6 | ||
|
|
8655349f00 | ||
|
|
d75edae498 | ||
|
|
6d5970adcb | ||
|
|
40f925e660 | ||
|
|
d9aab7db19 | ||
|
|
6f7a12c8be | ||
|
|
48d7d5a0b9 | ||
|
|
d459270d7d | ||
|
|
9e7a7ad920 | ||
|
|
ffcd3aa3c2 | ||
|
|
ecd933f94a | ||
|
|
9db8365930 | ||
|
|
64187169a0 | ||
|
|
f016ba700c | ||
|
|
02076b680e | ||
|
|
a6e16ad99f | ||
|
|
3f2de363c9 | ||
|
|
511d8d0cb4 | ||
|
|
4798d6b7e5 | ||
|
|
47775d2758 | ||
|
|
789e22ea08 | ||
|
|
fb8badbfd9 | ||
|
|
1c36f33a69 | ||
|
|
58dd31611d | ||
|
|
7d9033a212 | ||
|
|
564255978d | ||
|
|
cc87b603fb | ||
|
|
118a0b4214 | ||
|
|
b56580e3d1 | ||
|
|
2a1b77ff6b | ||
|
|
d94a54e392 | ||
|
|
1ab5db3183 | ||
|
|
560348fcfe | ||
|
|
e9f74bfb4d | ||
|
|
13eec1c31a | ||
|
|
aa64ca58f4 | ||
|
|
018c3a1cc6 | ||
|
|
e0bf4394b7 | ||
|
|
d684a3ede2 | ||
|
|
0bb1ab04d3 | ||
|
|
f35f5ccfe4 | ||
|
|
dc58737310 | ||
|
|
f246415f27 | ||
|
|
e7badbf124 | ||
|
|
caddb16b53 | ||
|
|
0d18206ae6 | ||
|
|
71c82c0f0d | ||
|
|
cc52fdcf5a | ||
|
|
6d31991fda | ||
|
|
7988f8cc1b | ||
|
|
59366d6f33 | ||
|
|
4f7970cb0e | ||
|
|
5794b2e977 | ||
|
|
291feff903 | ||
|
|
19ce81e995 | ||
|
|
4b20d5b954 | ||
|
|
90221a0e16 | ||
|
|
085036bc93 | ||
|
|
21186d0858 | ||
|
|
22e8d15f60 | ||
|
|
f258e6d17f | ||
|
|
a6a4185585 | ||
|
|
9924a574a8 | ||
|
|
7282d02c22 | ||
|
|
1ea62c3c60 | ||
|
|
5929a37d73 | ||
|
|
f4a0ec30ec | ||
|
|
c5c1e3c1ca | ||
|
|
449c74eb66 | ||
|
|
016717c8ef | ||
|
|
75bb80d343 | ||
|
|
c04c32e876 | ||
|
|
09025e0a8f | ||
|
|
13e845a5da | ||
|
|
2f4284f806 | ||
|
|
d4af5926cb | ||
|
|
0ad2f463ab | ||
|
|
3b49f9947f | ||
|
|
514b536f57 | ||
|
|
040143f557 | ||
|
|
c75d0cc989 | ||
|
|
701ac3f85d | ||
|
|
f283cff6bc | ||
|
|
d8e62cc541 | ||
|
|
8853c8a124 | ||
|
|
027fa4119b | ||
|
|
5424375e0d | ||
|
|
6007658c72 | ||
|
|
e0916858a8 | ||
|
|
1f397978d6 | ||
|
|
518f58885e | ||
|
|
ece24fa24b | ||
|
|
6524eb2b55 | ||
|
|
b16a6b1ab1 | ||
|
|
cda2ca43dd | ||
|
|
3375d30fad | ||
|
|
6b61c462a0 | ||
|
|
226fab5904 | ||
|
|
be2791462e | ||
|
|
9b38e6cb8f | ||
|
|
bce7830b86 | ||
|
|
4e6a3311a4 | ||
|
|
f8c1c87b01 | ||
|
|
94c3ae6533 | ||
|
|
8ca1ed17d4 | ||
|
|
a645363091 | ||
|
|
7db3c29e14 | ||
|
|
4c28475c0d | ||
|
|
c509f17789 | ||
|
|
6690ea7c0e | ||
|
|
347942668d | ||
|
|
1a3643d6f8 | ||
|
|
0af64210c5 | ||
|
|
7989b8eb0e | ||
|
|
4d902a03ca | ||
|
|
8af5b826b2 | ||
|
|
953b8e4fb2 | ||
|
|
95c4af6f84 | ||
|
|
f2be35ee94 | ||
|
|
056bc1af22 | ||
|
|
46501093ce | ||
|
|
0344e3f633 | ||
|
|
7882607c6e | ||
|
|
684c02b1c5 | ||
|
|
7d8889d045 | ||
|
|
a05b293582 | ||
|
|
c37085a1c7 | ||
|
|
bb8d7e2339 | ||
|
|
84c87d2dee | ||
|
|
710566e817 | ||
|
|
a1ca96017c | ||
|
|
686868519c | ||
|
|
f16f0e7e08 | ||
|
|
f96bf404e6 | ||
|
|
6d6a80dd4d | ||
|
|
94532e8598 | ||
|
|
254449ec1a | ||
|
|
3c69021c6c | ||
|
|
68955d67bb | ||
|
|
bc1eadad26 | ||
|
|
ebe6245243 | ||
|
|
d12c624b23 | ||
|
|
11c1668d65 | ||
|
|
158c27e52b | ||
|
|
36b777da8f | ||
|
|
012010957d | ||
|
|
b0f041328d | ||
|
|
94a12d9767 | ||
|
|
06cbb3e7f8 | ||
|
|
47de40856b | ||
|
|
c044fa2932 | ||
|
|
10f2145c15 | ||
|
|
de89355b05 | ||
|
|
54f9eed786 | ||
|
|
d8e73e9cb4 | ||
|
|
ba7f07e1c8 | ||
|
|
9353015ddc | ||
|
|
780e300815 | ||
|
|
4ed6464bbe | ||
|
|
8a9ed91051 | ||
|
|
784fabc288 | ||
|
|
1a25d1b866 | ||
|
|
b4bd2c3785 | ||
|
|
c72a18c7e4 | ||
|
|
51095f4a9f | ||
|
|
f2af835a02 | ||
|
|
fa8965f7bd | ||
|
|
e4da8a26b0 | ||
|
|
45351a504f | ||
|
|
48ce3fd4d0 | ||
|
|
98825a7d5f | ||
|
|
7011688812 | ||
|
|
ea8a3049cd | ||
|
|
d2c1e7aca5 | ||
|
|
2d80e831be | ||
|
|
c83e7b2b14 | ||
|
|
c7c71bc785 | ||
|
|
8c0e27b83b | ||
|
|
d275837da5 | ||
|
|
c1ecb703bf | ||
|
|
f804b56f92 | ||
|
|
d7a04c86f3 | ||
|
|
652b76ba50 | ||
|
|
359de1a1e5 | ||
|
|
eecec3106b | ||
|
|
f233b23569 | ||
|
|
0862a81322 | ||
|
|
6421fc9519 | ||
|
|
b1ef59bff9 | ||
|
|
cd7670ad11 | ||
|
|
79fa482f70 | ||
|
|
11705f7ccd | ||
|
|
11da4794b5 | ||
|
|
5cc6ae012a | ||
|
|
938c321a54 | ||
|
|
867422a2d9 | ||
|
|
8a547877b5 | ||
|
|
3e301af80c | ||
|
|
41ad6dc339 | ||
|
|
2f17f0d4ae | ||
|
|
f1f99a1d92 | ||
|
|
ad6fbe2bf3 | ||
|
|
e0bfad4807 | ||
|
|
3572ab9452 | ||
|
|
30ed285dcf | ||
|
|
2881491cc2 | ||
|
|
96f4d3e136 | ||
|
|
9e9ab6ae13 | ||
|
|
029cad9224 | ||
|
|
0029315c2e | ||
|
|
247c3b58ec | ||
|
|
7a165adfb8 | ||
|
|
5777319bfa | ||
|
|
9219c5a1ad | ||
|
|
096295d258 | ||
|
|
aa26e0c44d | ||
|
|
8fcd0c5e4c | ||
|
|
1a26487df3 | ||
|
|
7afedf59bf | ||
|
|
e81267995d | ||
|
|
9c206629b1 | ||
|
|
1e8dcdf4ea | ||
|
|
027e120c87 | ||
|
|
09de9e5fda | ||
|
|
b1c64bbd98 | ||
|
|
7ec6f6caad | ||
|
|
85babbeb01 | ||
|
|
0006223494 | ||
|
|
5f1bf408f7 | ||
|
|
8e8fd019c3 | ||
|
|
c7b98005bb | ||
|
|
508e95b9d8 | ||
|
|
5245df3ce3 | ||
|
|
ec66dd5649 | ||
|
|
d28c3f9ba3 | ||
|
|
64705b393a | ||
|
|
42b4557de7 | ||
|
|
d089a06566 | ||
|
|
4bbfdf8e85 | ||
|
|
1e6db0f0a5 | ||
|
|
0778c150b6 | ||
|
|
30a7170f50 | ||
|
|
b9ca828522 | ||
|
|
5f73d1e57a | ||
|
|
b0f4c4b8e0 | ||
|
|
10e343b8bb | ||
|
|
0ab5630ebf | ||
|
|
86a47ad533 | ||
|
|
fecf36a7ff | ||
|
|
16b392d360 | ||
|
|
dd6709c14a | ||
|
|
69622ad25a | ||
|
|
7e6a5642c1 | ||
|
|
ed9923dbf9 | ||
|
|
bb13d0b6f9 | ||
|
|
423e00eccd | ||
|
|
90ffa50718 | ||
|
|
4f0ed25e8e | ||
|
|
3f99cc7a6d | ||
|
|
a7e9d43411 | ||
|
|
c79bc6e32f | ||
|
|
a2b18aaec4 | ||
|
|
886e96f5d6 | ||
|
|
88388fc5b1 | ||
|
|
7cd4dec4df | ||
|
|
567c43f2f0 | ||
|
|
566a2509c9 | ||
|
|
dbaad2e169 | ||
|
|
2fdf9f9a8c | ||
|
|
ebfcef12a7 | ||
|
|
a0fc26afd7 | ||
|
|
5c8c8b6502 | ||
|
|
7e38749e40 | ||
|
|
e538336c5e | ||
|
|
f14b519756 | ||
|
|
034a1b3991 | ||
|
|
a2144d21c2 | ||
|
|
4a50a3161d | ||
|
|
d983b1f329 | ||
|
|
c1d5429245 | ||
|
|
c094016c33 | ||
|
|
5caf503784 | ||
|
|
93cd9f6880 | ||
|
|
7c7f5220da | ||
|
|
09e916fe18 | ||
|
|
471d9eed35 | ||
|
|
4457385281 | ||
|
|
c37d999ff3 | ||
|
|
6813b01c20 | ||
|
|
2e6032f81b | ||
|
|
001e9989b8 | ||
|
|
45dc0a2a72 | ||
|
|
dbb511b2f9 | ||
|
|
cbd13b49ef | ||
|
|
5902a7f113 | ||
|
|
70e71fc1da | ||
|
|
91d941b663 | ||
|
|
75ca1ff498 | ||
|
|
b0e5ad3ef5 | ||
|
|
0c12ff7662 | ||
|
|
d44c6c593d | ||
|
|
cdce35ec7a | ||
|
|
20210d7d54 | ||
|
|
8ade843108 | ||
|
|
faab0e841e | ||
|
|
efae6afd5a | ||
|
|
bb8f13d57b | ||
|
|
ff1903b1cc | ||
|
|
db193bd94a | ||
|
|
0ad1d57785 | ||
|
|
0c340286ef | ||
|
|
e60d681992 | ||
|
|
fff48260be | ||
|
|
2e7752559d | ||
|
|
aa000e46ed | ||
|
|
8ed441d968 | ||
|
|
c711a0c32c | ||
|
|
2bdfe2e12a | ||
|
|
1023fd90f1 | ||
|
|
059a59c746 | ||
|
|
2363a1fbb6 | ||
|
|
26b2cc816e | ||
|
|
93fc4950df | ||
|
|
f042076cab | ||
|
|
9a6fd69885 | ||
|
|
ffbf4b07f1 | ||
|
|
88ac570031 | ||
|
|
70c5d4eb43 | ||
|
|
1899f97b1e | ||
|
|
56cbb44f94 | ||
|
|
42c6b70f2b | ||
|
|
f673a36ccd | ||
|
|
80f319311e | ||
|
|
d256d5f7da | ||
|
|
0b7737a054 | ||
|
|
89f0c01acc | ||
|
|
d66cde252d | ||
|
|
c9103bd521 | ||
|
|
d2e87b0e13 | ||
|
|
a7eb042276 | ||
|
|
114796006f | ||
|
|
38932f14cc | ||
|
|
3ee1286cf4 | ||
|
|
ffef5923c6 | ||
|
|
e670c679df | ||
|
|
06ba235947 | ||
|
|
db72bb33f2 | ||
|
|
0c700cd1f8 | ||
|
|
721b63b197 | ||
|
|
41ca477b8a | ||
|
|
9fd5220e8c | ||
|
|
65be8cd2ce | ||
|
|
4b24ed4a21 | ||
|
|
93bdb4236e | ||
|
|
db82a14837 | ||
|
|
b6cb460085 | ||
|
|
358bb18f8f | ||
|
|
bd2cc60aae | ||
|
|
f00bd31eaf | ||
|
|
191ca88daa | ||
|
|
611571d566 | ||
|
|
11550edcd0 | ||
|
|
3c51f44190 | ||
|
|
ee3fbcae78 | ||
|
|
63ad119e63 | ||
|
|
bfcae3fc70 | ||
|
|
21b261b2d3 | ||
|
|
9ac94167d2 | ||
|
|
170c782ba2 | ||
|
|
7465259340 | ||
|
|
c871e8b64e | ||
|
|
1dfaa93568 | ||
|
|
866c480634 | ||
|
|
ae6fbc1acb | ||
|
|
1cbf9c5eb8 | ||
|
|
210da6c94b | ||
|
|
5be889d169 | ||
|
|
03f992bfc5 | ||
|
|
db6afdbfbb | ||
|
|
624c562c1f | ||
|
|
4809eccb9e | ||
|
|
1f9f46175c | ||
|
|
71b16e1824 | ||
|
|
3975b2c6e3 | ||
|
|
48bcb02f82 | ||
|
|
9fd83e56e2 | ||
|
|
a40742a45c | ||
|
|
4d10e7e290 | ||
|
|
83f1a1ef8e | ||
|
|
47581eb453 | ||
|
|
045ac03837 | ||
|
|
6439845d32 | ||
|
|
0b0721b9d3 | ||
|
|
f1ba65affa | ||
|
|
e60bdbf80c | ||
|
|
2269b500f3 | ||
|
|
089f2e964c | ||
|
|
1e477f71ef | ||
|
|
430e8efd42 | ||
|
|
bddd7e5417 | ||
|
|
10deb4c51a | ||
|
|
530c3a5576 | ||
|
|
4e5cb34051 | ||
|
|
e7c5eb6bee | ||
|
|
f2cb6ed1a6 | ||
|
|
ce745204f7 | ||
|
|
8b3c9f2f72 | ||
|
|
2aa1c85972 | ||
|
|
766e5db363 | ||
|
|
c1504e104d | ||
|
|
3705b740c9 | ||
|
|
85889ee338 | ||
|
|
32254fbed8 | ||
|
|
62fbac2d19 | ||
|
|
6b02bb973f | ||
|
|
1ad15035de | ||
|
|
dd7a21010a | ||
|
|
f69ab641f7 | ||
|
|
27308b59ea | ||
|
|
f1aa9fe906 | ||
|
|
112b28342a | ||
|
|
2f9fe92b6c | ||
|
|
4a45c78512 | ||
|
|
0c78f66c21 | ||
|
|
be6f934e7b | ||
|
|
79fa11f2c9 | ||
|
|
349966a7c3 | ||
|
|
4867825367 | ||
|
|
36686afe04 | ||
|
|
9547896074 | ||
|
|
4ecb737ea7 | ||
|
|
0147f398ec | ||
|
|
3fd0420b52 | ||
|
|
decba39373 | ||
|
|
15972a9203 | ||
|
|
94c0a52824 | ||
|
|
d583f52d7e | ||
|
|
9b243f90ee | ||
|
|
18168e4577 | ||
|
|
a18e5454ce | ||
|
|
7bf16f2891 | ||
|
|
8491387a15 | ||
|
|
123ae18a64 | ||
|
|
f3a19597fc | ||
|
|
6c6ccbf07c | ||
|
|
09af9a2576 | ||
|
|
cf813d7eb4 | ||
|
|
f0ca523dfb | ||
|
|
6a08443853 | ||
|
|
030b9b0c82 | ||
|
|
8a0b511649 | ||
|
|
7853b830ae | ||
|
|
77eb7f7821 | ||
|
|
65e71ac56f | ||
|
|
a2a1bcb77b | ||
|
|
e8fadc638c | ||
|
|
507a8330b7 | ||
|
|
1dc1c99c33 | ||
|
|
0cd89585e2 | ||
|
|
c54148c291 | ||
|
|
f7d7fa5031 | ||
|
|
d959bd6c34 | ||
|
|
92240d3e8b | ||
|
|
0c634a4fa6 | ||
|
|
c8e2414a70 | ||
|
|
a6956b34db | ||
|
|
055c2ec202 | ||
|
|
1c0e03eadc | ||
|
|
f8c44cf2d3 | ||
|
|
d99eeb1e1e | ||
|
|
c42a4d9d1c | ||
|
|
2b8eb11bc3 | ||
|
|
f4f62c6edf | ||
|
|
142f75e662 | ||
|
|
1bc19921ff | ||
|
|
d901b795f7 | ||
|
|
de19e3abec | ||
|
|
ee1ab72d0a | ||
|
|
c699dd71af | ||
|
|
3452bafd4b | ||
|
|
0aabac338d | ||
|
|
a9a25a9197 | ||
|
|
aa295e9688 | ||
|
|
9cf21b1192 | ||
|
|
7efb6fc125 | ||
|
|
a050af7985 | ||
|
|
25e3fd90c5 | ||
|
|
e79384a3c4 | ||
|
|
c784af67da | ||
|
|
74d4681f33 | ||
|
|
eaa939eda3 | ||
|
|
a3b21debb0 | ||
|
|
db9168e179 | ||
|
|
d68a5106a5 | ||
|
|
5244d7af1e | ||
|
|
0ee095617e | ||
|
|
8d7d022576 | ||
|
|
098cf78753 | ||
|
|
4131811e32 | ||
|
|
260cd62329 | ||
|
|
b6b8ce55c6 | ||
|
|
1d3e5a60e2 | ||
|
|
b2397cfd54 | ||
|
|
15ef3bdadb | ||
|
|
c353e713cc | ||
|
|
1eaaad320f | ||
|
|
e0c0071d8b | ||
|
|
0a7c274f33 | ||
|
|
d4621f8b8a | ||
|
|
5b0c1fd16e | ||
|
|
6b5847f149 | ||
|
|
b227d89a01 | ||
|
|
a4191556ea | ||
|
|
a7d90c0b39 | ||
|
|
6edef4ec97 | ||
|
|
17f7ae7daa | ||
|
|
03d33f2074 | ||
|
|
8787d8ad43 | ||
|
|
69f98aa756 | ||
|
|
9620faafe1 | ||
|
|
2ba0b164fc | ||
|
|
77b9b2e8ce | ||
|
|
58be436aaa | ||
|
|
5995eb8b8e | ||
|
|
0e4f942b15 | ||
|
|
c14f773ed4 | ||
|
|
3ef08a53d1 | ||
|
|
67d32c5a96 | ||
|
|
e351793043 | ||
|
|
f0a987e7a2 | ||
|
|
c0354961f7 | ||
|
|
4c8c8dcdab | ||
|
|
cae80096e1 | ||
|
|
45d4fcc0bf | ||
|
|
da5380a472 | ||
|
|
b27544663e | ||
|
|
75c35aa9e5 | ||
|
|
ad0fd8d5c8 | ||
|
|
c60cd1fabb | ||
|
|
7cfb6258d5 | ||
|
|
ff1bc2577f | ||
|
|
07ab3621b3 | ||
|
|
0af3f3fcce | ||
|
|
cb8a70744d | ||
|
|
c6a8d3e251 | ||
|
|
d871292d39 | ||
|
|
255febcd70 | ||
|
|
c7d8f77fb4 | ||
|
|
248de4ef0f | ||
|
|
56ae5d2c33 | ||
|
|
2cc575d74b | ||
|
|
b0b68d16a4 | ||
|
|
45fd510e15 | ||
|
|
0376a58374 | ||
|
|
b1d1d2c7f8 | ||
|
|
6de14c91e4 | ||
|
|
a04cbeba78 | ||
|
|
82610e281d | ||
|
|
e9b3213d8b | ||
|
|
313ee50bf2 | ||
|
|
fca72e3fad | ||
|
|
97657da95d | ||
|
|
f32240ba65 | ||
|
|
1d8d20a7d7 | ||
|
|
5fba2685b1 | ||
|
|
2c39551560 | ||
|
|
265ca8b433 | ||
|
|
8c4b33ec17 | ||
|
|
937bf6f57a | ||
|
|
e2f142ed28 | ||
|
|
9a835690aa | ||
|
|
5f4ec1c446 | ||
|
|
7b11516520 | ||
|
|
4a6543b0c6 | ||
|
|
fa197c1b7f | ||
|
|
ab4ab7e63b | ||
|
|
b88a8e605a | ||
|
|
519d8fc64a | ||
|
|
8032fde262 | ||
|
|
02b4b0b9b6 | ||
|
|
933c820f20 | ||
|
|
8476fdb77f | ||
|
|
ae1f280062 | ||
|
|
d58dd28051 | ||
|
|
a212382da6 | ||
|
|
b1819ff755 | ||
|
|
2317305f0e | ||
|
|
da5f7e27c4 | ||
|
|
4c4dd71195 | ||
|
|
61c3d3c34a | ||
|
|
59d4e30469 | ||
|
|
e0dd34df2b | ||
|
|
41366d9376 | ||
|
|
1779b8d67e | ||
|
|
b673cbe411 | ||
|
|
1a595c5043 | ||
|
|
bce5ae88ee | ||
|
|
b81d15cdef | ||
|
|
ec6747ac09 | ||
|
|
5cd35bbfb5 | ||
|
|
1b07509e18 | ||
|
|
35211b94db | ||
|
|
0e9338a0e4 | ||
|
|
95b099d62c | ||
|
|
b295963d8d | ||
|
|
884ca797d8 | ||
|
|
3664b4acec | ||
|
|
95f33310bf | ||
|
|
a1500051b9 | ||
|
|
be1a6cc985 | ||
|
|
32525a0204 | ||
|
|
8b64c8afd3 | ||
|
|
2795413fc1 | ||
|
|
8db9fc3f17 | ||
|
|
d7c2fb8a02 | ||
|
|
6c9d09f6c3 | ||
|
|
1482fe3e1b | ||
|
|
c2f0422a68 | ||
|
|
4b3a7af308 | ||
|
|
7b2cd6e4b0 | ||
|
|
60dbe28dca | ||
|
|
3dde8c5905 | ||
|
|
9207ef357f | ||
|
|
ce7ea27255 | ||
|
|
c3eb701c56 | ||
|
|
180c1fe185 | ||
|
|
9b3138102d | ||
|
|
e43412c02f | ||
|
|
a223fad28c | ||
|
|
9ade31a813 | ||
|
|
fd91024b8d | ||
|
|
0d9526ed72 | ||
|
|
d4e51a1b51 | ||
|
|
ded26df5d0 | ||
|
|
a3ba44771f | ||
|
|
83f4ac980e | ||
|
|
5da102c058 | ||
|
|
27608327af | ||
|
|
fcbbd53dd8 | ||
|
|
76aaab319c | ||
|
|
6ea6a46c15 | ||
|
|
c0f3e62a10 | ||
|
|
5f71660c7a | ||
|
|
e6b15de5a4 | ||
|
|
bf74569906 | ||
|
|
b70f1f84be | ||
|
|
a2209e73fc | ||
|
|
f77ebe3af7 | ||
|
|
8c4370780d | ||
|
|
e4b352f1ce | ||
|
|
a679e33d54 | ||
|
|
e477ce3d9a | ||
|
|
f15d7ac445 | ||
|
|
d36af364bf | ||
|
|
b0ebcf86e6 | ||
|
|
247ec75c9e | ||
|
|
3b43bf3579 | ||
|
|
2be6d5cdef | ||
|
|
fef7526af4 | ||
|
|
88ee26ecf8 | ||
|
|
947c602cb0 | ||
|
|
fd0cf4e4e3 | ||
|
|
0d11bffa82 | ||
|
|
c9a9c48de3 | ||
|
|
fbbcb58e3f | ||
|
|
ed9dbea34a | ||
|
|
9ccca42011 | ||
|
|
d7bc92e465 | ||
|
|
5d29ebfde2 | ||
|
|
efa14f2dcd | ||
|
|
2e07802a05 | ||
|
|
34a83a46d9 | ||
|
|
9db5c68a64 | ||
|
|
5dac84c511 | ||
|
|
ce834c9b18 | ||
|
|
0af5f626bc | ||
|
|
0d68186dfe | ||
|
|
65e226d02d | ||
|
|
15d0654cd7 | ||
|
|
f7c36efab8 | ||
|
|
09e372f37b | ||
|
|
a020e06c3d | ||
|
|
650f2caf42 | ||
|
|
bfaa5a9878 | ||
|
|
7d22fc727b | ||
|
|
e78db0d549 | ||
|
|
4a610d9868 | ||
|
|
2c08ab1e52 | ||
|
|
70c26493c4 | ||
|
|
e5f45550d4 | ||
|
|
80c196d863 | ||
|
|
516ee4b762 | ||
|
|
7371e15ebb | ||
|
|
b6f6f79c00 | ||
|
|
d8dd38dcdd | ||
|
|
1384c2b477 | ||
|
|
2006a44fdd | ||
|
|
f7c04c9f7e | ||
|
|
1dbb36bd77 | ||
|
|
54cabebbfa | ||
|
|
f31c2296dd | ||
|
|
6f66fd9597 | ||
|
|
8c33bd828a | ||
|
|
068352de91 | ||
|
|
f5c166906b | ||
|
|
514772f5c2 | ||
|
|
2e0c2aa8bc | ||
|
|
bfd641f1b1 | ||
|
|
1c45af855d | ||
|
|
5d7cf75bed | ||
|
|
04ee23b7b5 | ||
|
|
99c3c71be8 | ||
|
|
0c2fb54d14 | ||
|
|
eaf875dfd5 | ||
|
|
29e61087ac | ||
|
|
ef989e7909 | ||
|
|
ab1fd464cf | ||
|
|
4a042b73b8 | ||
|
|
b416a7de09 | ||
|
|
ebec631cde | ||
|
|
cd6a751a68 | ||
|
|
f90692b526 | ||
|
|
b4ff72d424 | ||
|
|
61de002e0e | ||
|
|
6c063c856c | ||
|
|
a075a0b29b | ||
|
|
0e85e70470 | ||
|
|
0e84d1dad1 | ||
|
|
092b3bf9c2 | ||
|
|
87cf688e27 | ||
|
|
892cab3adf | ||
|
|
c547f50dc8 | ||
|
|
952bcecb12 | ||
|
|
1da97c3cd6 | ||
|
|
b9abc13364 | ||
|
|
fcd2ffa630 | ||
|
|
1f769bc7b5 | ||
|
|
e84a5ad62a | ||
|
|
5a481aeb5e | ||
|
|
24cea1d8d2 | ||
|
|
134f368953 | ||
|
|
8a6749e38b | ||
|
|
0722639001 | ||
|
|
e372dd8ddf | ||
|
|
c66022eaa8 | ||
|
|
3b873fc06c | ||
|
|
f2ac7cca28 | ||
|
|
d21d909de6 | ||
|
|
7c476ec104 | ||
|
|
3716772a06 | ||
|
|
c1100a5c62 | ||
|
|
0ae1332480 | ||
|
|
222debc335 | ||
|
|
7702ac5475 | ||
|
|
b4f4b10332 | ||
|
|
fb795a22c8 | ||
|
|
e5a4af88cc | ||
|
|
f68508a9ef | ||
|
|
1e4adf115c | ||
|
|
dbc8a2b7b2 | ||
|
|
f339bfe45d | ||
|
|
a78b88c2a4 | ||
|
|
4a338ad94e | ||
|
|
03d0e38f15 | ||
|
|
7da16b469c | ||
|
|
c80fcc5494 | ||
|
|
0286396175 | ||
|
|
edf381c914 | ||
|
|
58d85518f0 | ||
|
|
32e8ebf4f8 | ||
|
|
c8cba6ba91 | ||
|
|
fba5487231 | ||
|
|
9d81fbcbcb | ||
|
|
40c55b3515 | ||
|
|
e5aaaff32e | ||
|
|
6071b138f0 | ||
|
|
71174f5d40 | ||
|
|
bb4ca4ff9e | ||
|
|
93f42e9a67 | ||
|
|
2b6c1ec771 | ||
|
|
958546fd0c | ||
|
|
d263494229 | ||
|
|
12d51318a8 | ||
|
|
aa8861643f | ||
|
|
0f0e4e35ce | ||
|
|
79f63a794d | ||
|
|
47e01dadb7 | ||
|
|
3bfa2bd9e4 | ||
|
|
b1aac49824 | ||
|
|
16fdfa3cb1 | ||
|
|
9c43badbfc | ||
|
|
96689b8e67 | ||
|
|
95b2a56f80 | ||
|
|
6c33f6ff08 | ||
|
|
ab515920de | ||
|
|
46fd65f98a | ||
|
|
e9986c9667 | ||
|
|
fec40dd91c | ||
|
|
e8bffd8dc6 | ||
|
|
59e6271373 | ||
|
|
0dbb0b6e12 | ||
|
|
5d1c166606 | ||
|
|
366463ac4e | ||
|
|
ed5d4f5fcd | ||
|
|
787bc2243f | ||
|
|
8b5fccdd0d | ||
|
|
fa79467c19 | ||
|
|
5a4577b7ec | ||
|
|
0c82c60c03 | ||
|
|
84e33ec18a | ||
|
|
779be53910 | ||
|
|
cda6e3c204 | ||
|
|
c73aee1633 | ||
|
|
d486b8b4cf | ||
|
|
31909ba17b | ||
|
|
27dc30ca57 | ||
|
|
f5b7ddcf0e | ||
|
|
f1aac3e9e2 | ||
|
|
0f626dada2 | ||
|
|
74f4c74f47 | ||
|
|
3e93ab0fac | ||
|
|
4ac4ec58a8 | ||
|
|
af552414ac | ||
|
|
728d7c5d24 | ||
|
|
ee17b54872 | ||
|
|
373a557ad2 | ||
|
|
062eeb8ac0 | ||
|
|
473a7fc647 | ||
|
|
4ddd9dd874 | ||
|
|
05dd048410 | ||
|
|
c2c4afa094 | ||
|
|
be2567f478 | ||
|
|
e9e9c9f702 | ||
|
|
1e3d653d1c | ||
|
|
63f3f3899e | ||
|
|
08362d1bb6 | ||
|
|
f1d3d78f89 | ||
|
|
5f084b9d7c | ||
|
|
224d694ffa | ||
|
|
1be4b06d33 | ||
|
|
155c3a4b50 | ||
|
|
371f912c1d | ||
|
|
41c47fbc58 | ||
|
|
167030c15c | ||
|
|
7403a07614 | ||
|
|
fd0bad9a91 | ||
|
|
c2381ac3f5 | ||
|
|
ee18fbac19 | ||
|
|
b83ec99e4f | ||
|
|
72bd03d368 | ||
|
|
a6ee68efe8 | ||
|
|
795ca64ac0 | ||
|
|
ee26df3b68 | ||
|
|
bc0cf84297 | ||
|
|
049f846980 | ||
|
|
67308b8e3a | ||
|
|
8c9cdb28d0 | ||
|
|
dd30b30b34 | ||
|
|
6446097840 | ||
|
|
589cf2afd8 | ||
|
|
fb1928d5ec | ||
|
|
552b41f855 | ||
|
|
e2a036192a | ||
|
|
b6c5f670b3 | ||
|
|
ecac1c5b78 | ||
|
|
1d3f124845 | ||
|
|
d0b39df3e2 | ||
|
|
beb52670fa | ||
|
|
c924407569 | ||
|
|
bb72002452 | ||
|
|
78f045ddf2 | ||
|
|
ba49220e43 | ||
|
|
857bceba76 | ||
|
|
859280c2d7 | ||
|
|
e8ac5dbe8d | ||
|
|
86ec75b05e | ||
|
|
6b00fdb19e | ||
|
|
b9707ea486 | ||
|
|
f9dd71c05a | ||
|
|
0720a9b8f0 | ||
|
|
0289733f7f | ||
|
|
50ed8ad1e5 | ||
|
|
a10fabd927 | ||
|
|
0dd9fdf7e6 | ||
|
|
ade5f386b6 | ||
|
|
315b135a3b | ||
|
|
bc3d1daf11 | ||
|
|
50d738c7b6 | ||
|
|
0a23ac1401 | ||
|
|
9cbfb4ccbe | ||
|
|
7c1a76d38e | ||
|
|
b501b86656 | ||
|
|
f118cff5c0 | ||
|
|
66d7a9e520 | ||
|
|
a3424ce020 | ||
|
|
7cb72b25be | ||
|
|
f3584b02ac | ||
|
|
f2aaf9cc26 | ||
|
|
ea0bab5bd6 | ||
|
|
78be6f9839 | ||
|
|
a7df5c7fac | ||
|
|
516a6be98e | ||
|
|
7077e30d94 | ||
|
|
21b4053b8b | ||
|
|
85c634480d | ||
|
|
54eefe2295 | ||
|
|
b32dbc3ac5 | ||
|
|
4a5d089e5d | ||
|
|
22cad5a2ab | ||
|
|
acbebd7102 | ||
|
|
301ae12169 | ||
|
|
f04bdcee69 | ||
|
|
d4b78fbf87 | ||
|
|
500fbc9190 | ||
|
|
420f7e9b4e | ||
|
|
b273c6083f | ||
|
|
8877c705c5 | ||
|
|
1e30f794fe | ||
|
|
29ad82db7c | ||
|
|
a9046be00c | ||
|
|
a70efc95c6 | ||
|
|
b4b8774110 | ||
|
|
d87e03b0cf | ||
|
|
af07ccb87e | ||
|
|
dc43918a77 | ||
|
|
a04b131394 | ||
|
|
874f18fa6a | ||
|
|
fdc93e5130 | ||
|
|
6109e18fe6 | ||
|
|
27aca28523 | ||
|
|
2ac4aacee5 | ||
|
|
824a741634 | ||
|
|
819722e7da | ||
|
|
959d442690 | ||
|
|
b20868328f | ||
|
|
679c729985 | ||
|
|
bc2ca273a5 | ||
|
|
8a2612878d | ||
|
|
dd76d149ee | ||
|
|
2770d0fbec | ||
|
|
55b2c1e186 | ||
|
|
c4c291056b | ||
|
|
b80b81ada6 | ||
|
|
a0f3d44832 | ||
|
|
d9e4c00ccf | ||
|
|
c34a186eaf | ||
|
|
be27c930d3 | ||
|
|
66818872c2 | ||
|
|
cc1ac368b3 | ||
|
|
03e22098ca | ||
|
|
724b5eb1e0 | ||
|
|
45a1ce4b55 | ||
|
|
3e5cb2e30b | ||
|
|
d0a4c6aaf1 | ||
|
|
be4bcb7390 | ||
|
|
a63c3aa4c2 | ||
|
|
e8e43d97f2 | ||
|
|
9939ff4452 | ||
|
|
b69bbc899e | ||
|
|
f0cba24cc7 | ||
|
|
fd5fa0e798 | ||
|
|
1ba1d53884 | ||
|
|
00a118b901 | ||
|
|
ba2ea55884 | ||
|
|
70b4c3dd0f | ||
|
|
412e19252c | ||
|
|
73e1974583 | ||
|
|
25c57d645b | ||
|
|
a6c6021923 | ||
|
|
2886ac9d7c | ||
|
|
c121414767 | ||
|
|
35f02ef7a9 | ||
|
|
ffeb972a82 | ||
|
|
f20a74674f | ||
|
|
03396fbbe2 | ||
|
|
54a5c0805e | ||
|
|
486cb66b6c | ||
|
|
e5d7a344c7 | ||
|
|
60fe0ed25f | ||
|
|
04741c702a | ||
|
|
6e190fe903 | ||
|
|
5bb3e65eb9 | ||
|
|
c3b29ffcd1 | ||
|
|
a889c3e97b | ||
|
|
bd578ca7cd | ||
|
|
2a9a115c31 | ||
|
|
4d1848a5e1 | ||
|
|
4bd8f777e0 | ||
|
|
4654a9011b | ||
|
|
22a5dc148a | ||
|
|
88dc4c0607 | ||
|
|
0a7c47fa70 | ||
|
|
e6f311ebba | ||
|
|
88d09f0fef | ||
|
|
7467d87e36 | ||
|
|
b50e793a9c | ||
|
|
1147390576 | ||
|
|
539785f079 | ||
|
|
b99b516346 | ||
|
|
c0dc4f4236 | ||
|
|
5b8f664530 | ||
|
|
cc490692ad | ||
|
|
5ef415c87d | ||
|
|
ff3c67409d | ||
|
|
582a9bae31 | ||
|
|
95f51ed935 | ||
|
|
0dca22c219 | ||
|
|
eaf67e197b | ||
|
|
b8db918348 | ||
|
|
c865073605 | ||
|
|
192ccbec25 | ||
|
|
b8b3b29d01 | ||
|
|
00ea9a4393 | ||
|
|
267392d0b7 | ||
|
|
e5f041208f | ||
|
|
82010353c6 | ||
|
|
7daf4d1f58 | ||
|
|
ebb940ee0e | ||
|
|
1ce8c98837 | ||
|
|
257948cbe1 | ||
|
|
8971e0aa1a | ||
|
|
2209b050b0 | ||
|
|
b5a876a93e | ||
|
|
4c64ee24d5 | ||
|
|
1a3376374f | ||
|
|
ee88560090 | ||
|
|
aae7eba068 | ||
|
|
6715bc34d8 | ||
|
|
55d0ea5e22 | ||
|
|
11c692b146 | ||
|
|
ab47bd2e7b | ||
|
|
6dd9933d55 | ||
|
|
d08d398b47 | ||
|
|
aa3903d8f0 | ||
|
|
26f9030cef | ||
|
|
0500a10671 | ||
|
|
c3ae2d3eda | ||
|
|
e502c51886 | ||
|
|
063c1aa6c0 | ||
|
|
5e5db9193e | ||
|
|
26a38fc56c | ||
|
|
aad0558a9c | ||
|
|
a911f975da | ||
|
|
a99c8fbc88 | ||
|
|
79525227a9 | ||
|
|
66b8eb72bf | ||
|
|
1eff269b80 | ||
|
|
2dc01b528c | ||
|
|
30e200896d | ||
|
|
7d2e827e6f | ||
|
|
94e6b3086b | ||
|
|
0849e90574 | ||
|
|
d3eef33371 | ||
|
|
1cee0d10e5 | ||
|
|
3f044b407a | ||
|
|
b25ce3760b | ||
|
|
6e810761f8 | ||
|
|
6dea80e13e | ||
|
|
a715616a6a | ||
|
|
e87db432d5 | ||
|
|
0b4b89dcbd | ||
|
|
0e980051e3 | ||
|
|
4bd489a530 | ||
|
|
ed02c0dbc1 | ||
|
|
81e2432426 | ||
|
|
3a14099831 | ||
|
|
84712967b0 | ||
|
|
1fc70b7591 | ||
|
|
b9f8345964 | ||
|
|
fcd9e674d5 | ||
|
|
2cf2dfaea5 | ||
|
|
797be4e57c | ||
|
|
2478f1478f | ||
|
|
58cd508be4 | ||
|
|
9ca094f4f8 | ||
|
|
9ed9878193 | ||
|
|
c878a47f92 | ||
|
|
42d7a8860a | ||
|
|
718824f359 | ||
|
|
3b5b649530 | ||
|
|
8702af0c42 | ||
|
|
b038157f2f | ||
|
|
0033bdd570 | ||
|
|
99b40cac43 | ||
|
|
7fa91f98c6 | ||
|
|
a6e3f48044 | ||
|
|
d25921f6c8 | ||
|
|
e1986dc8eb | ||
|
|
ebba5b860f | ||
|
|
4beff8932e | ||
|
|
e26bd9adfb | ||
|
|
2eadc7b5ea | ||
|
|
a15aeade6a | ||
|
|
1990b7fad5 | ||
|
|
d81d5a37f8 | ||
|
|
1c1da0b080 | ||
|
|
4063bce178 | ||
|
|
b4d33c6472 | ||
|
|
44005c607d | ||
|
|
c17852a583 | ||
|
|
f94b22666b | ||
|
|
3c8c690a79 | ||
|
|
6f416ffe79 | ||
|
|
e4f8fe9ea2 | ||
|
|
003738149e | ||
|
|
6f39223787 | ||
|
|
06649c2207 | ||
|
|
18f51becd8 | ||
|
|
916792abea | ||
|
|
c8f8e019f6 | ||
|
|
7b6c6bb930 | ||
|
|
b826993a0d | ||
|
|
00385c8e15 | ||
|
|
5b982766fb | ||
|
|
be27dfd918 | ||
|
|
a82089aff3 | ||
|
|
215ba8bfbf | ||
|
|
7b1e9185f7 | ||
|
|
8c756e99c1 | ||
|
|
d2384e74cd | ||
|
|
b2ff2852bd | ||
|
|
3b4505af27 | ||
|
|
87eee126e5 | ||
|
|
6234f04457 | ||
|
|
c8e808082f | ||
|
|
b2f2642c82 | ||
|
|
0f77730011 | ||
|
|
b062d56928 | ||
|
|
a3f8552b80 | ||
|
|
8faf5a81ca | ||
|
|
7d7c0ae320 | ||
|
|
2bd8b71927 | ||
|
|
19a323ec77 | ||
|
|
29ee95165e | ||
|
|
c618a31e44 | ||
|
|
f972de507f | ||
|
|
51a0be31d5 | ||
|
|
d986c12564 | ||
|
|
1ae17b121e | ||
|
|
afb294f170 | ||
|
|
2b63fa343a | ||
|
|
35121f1141 | ||
|
|
9d0f26fede | ||
|
|
f0289b73b8 | ||
|
|
1009619ecd | ||
|
|
f30b1b1e08 | ||
|
|
d151f39a22 | ||
|
|
be6d4accff | ||
|
|
69e71202ee | ||
|
|
fece284aee | ||
|
|
4bcb44bcb2 | ||
|
|
0891dbf5a8 | ||
|
|
b5b5a86025 | ||
|
|
3fcbe831d7 | ||
|
|
d253151296 | ||
|
|
4e9beb86b0 | ||
|
|
7f85b49f3f | ||
|
|
1ea8c56631 | ||
|
|
5d76cbee26 | ||
|
|
682e4af619 | ||
|
|
c446476fbc | ||
|
|
e18a05001e | ||
|
|
0685f8b9c0 | ||
|
|
bdd1d4e8c1 | ||
|
|
bf6923f909 | ||
|
|
faa37c3322 | ||
|
|
1fe5b07f86 | ||
|
|
7a9ad3933b | ||
|
|
df2e447362 | ||
|
|
b2033f3dcd | ||
|
|
186bce852d | ||
|
|
e1494441b0 | ||
|
|
1b67c130c7 | ||
|
|
628b980655 | ||
|
|
0e04a17380 | ||
|
|
cee1a14ebd | ||
|
|
3862205053 | ||
|
|
9696f044a0 | ||
|
|
b61a0f2c94 | ||
|
|
afb2e3a8a2 | ||
|
|
65cc0a0ed5 | ||
|
|
dba6f2ec6a | ||
|
|
b39ea03ba6 | ||
|
|
528483b905 | ||
|
|
fb7434f1b4 | ||
|
|
a239e6405b | ||
|
|
d5c00b81d7 | ||
|
|
590f6c8c8b | ||
|
|
edf2495a9f | ||
|
|
ed0a034414 | ||
|
|
3e33e0d0e1 | ||
|
|
c9e1c2711e | ||
|
|
1f0420dc1f | ||
|
|
f0320c6ff9 | ||
|
|
904eb1364c | ||
|
|
e5ef184515 | ||
|
|
2a4111643c | ||
|
|
53ffe057b2 | ||
|
|
b2632e1727 | ||
|
|
84554d6dea | ||
|
|
6fd8f8380b | ||
|
|
5330929efd | ||
|
|
c67bc9938c | ||
|
|
f41f0e94be | ||
|
|
74b1c6f4ed | ||
|
|
54d7e20baa | ||
|
|
221d88c52c | ||
|
|
eb3c8050fe | ||
|
|
fdab854799 | ||
|
|
ba32761a0c | ||
|
|
6d002838a5 | ||
|
|
d8f53db387 | ||
|
|
f15db1637e | ||
|
|
5f98e2fdc5 | ||
|
|
603dc9f9c6 | ||
|
|
0692079384 | ||
|
|
e046cdce45 | ||
|
|
595419df77 | ||
|
|
1a641afaa8 | ||
|
|
29c73ae90f | ||
|
|
e055f99f63 | ||
|
|
888d4797d0 | ||
|
|
b95d63e974 | ||
|
|
195abb59ff | ||
|
|
306ceba474 | ||
|
|
2be1476130 | ||
|
|
ca80356c27 | ||
|
|
eed34d9b7d | ||
|
|
1144ab32b7 | ||
|
|
0061e609d4 | ||
|
|
680b64c98f | ||
|
|
325048efcb | ||
|
|
aedb293d50 | ||
|
|
6cdc1943fb | ||
|
|
9ff40875c2 | ||
|
|
3a851d59fe | ||
|
|
64de7abada | ||
|
|
6d9feebedd | ||
|
|
441658eb7a | ||
|
|
01a441a99c | ||
|
|
1d10141c1d | ||
|
|
952313acee | ||
|
|
d537b742dc | ||
|
|
f3b706bcc2 | ||
|
|
2a57af944f | ||
|
|
3f42b93300 | ||
|
|
59a58eb886 | ||
|
|
d91d5bcd9b | ||
|
|
c6a08c79e1 | ||
|
|
d550b65bc7 | ||
|
|
42418ef393 | ||
|
|
12f4156ae0 | ||
|
|
ff58873fcb | ||
|
|
925c72f6aa | ||
|
|
345d853e2d | ||
|
|
10b064dc40 | ||
|
|
75a7187a87 | ||
|
|
6182e00c31 | ||
|
|
e3ba93a6b8 | ||
|
|
109d8cacbc | ||
|
|
3bcc18f035 | ||
|
|
92baa1affb | ||
|
|
32a9457de3 | ||
|
|
32c147fa16 | ||
|
|
d61d75f8bb | ||
|
|
eae6cd5396 | ||
|
|
6f16f230d1 | ||
|
|
f458a057e8 | ||
|
|
d013300fa3 | ||
|
|
d6b8394044 | ||
|
|
c1fa630602 | ||
|
|
28a03dadaf | ||
|
|
29cfc2ea6b | ||
|
|
f4c776f10e | ||
|
|
04be6bc38b | ||
|
|
4f0bbeeab0 | ||
|
|
5a356a8d75 | ||
|
|
7f35f46eaa | ||
|
|
ea7be67d83 | ||
|
|
8f0d65766d | ||
|
|
a140f318a2 | ||
|
|
d0a2d1644f | ||
|
|
e69b153e1c | ||
|
|
d19d383738 | ||
|
|
253f288323 | ||
|
|
d6ce0536ca | ||
|
|
0168c01915 | ||
|
|
7329fec67a | ||
|
|
5fea22294e | ||
|
|
669124a6b3 | ||
|
|
c44d141c07 | ||
|
|
0b30e00b8c | ||
|
|
1e7bd1bf48 | ||
|
|
c2c4d6aa02 | ||
|
|
7e0c64191c | ||
|
|
323e4e971a | ||
|
|
99b4f8f8fc | ||
|
|
7c1cf76c5c | ||
|
|
305e1b7af6 | ||
|
|
6880a70227 | ||
|
|
0482969755 | ||
|
|
4c9b429dae | ||
|
|
60b8400e29 | ||
|
|
7260be98d6 | ||
|
|
be94094de7 | ||
|
|
645077f39b | ||
|
|
b42940441d | ||
|
|
fc7071c04e | ||
|
|
de887a4e3f | ||
|
|
7f629309c7 | ||
|
|
fa45e209d5 | ||
|
|
40aec6cd0d | ||
|
|
969ae7aeca | ||
|
|
a64bbd34f3 | ||
|
|
79acf83d6f | ||
|
|
786e8d0be1 | ||
|
|
2757850f28 | ||
|
|
7c6f39f3b5 | ||
|
|
70723d0437 | ||
|
|
bd9b0f798b | ||
|
|
0c406b2ad8 | ||
|
|
822891541c | ||
|
|
bf064fd4e3 | ||
|
|
6c9e055d42 | ||
|
|
7455d1bfb2 | ||
|
|
7b923b6625 | ||
|
|
bcd18e9395 | ||
|
|
082d577834 | ||
|
|
68bf4f9df3 | ||
|
|
9348698aac | ||
|
|
979025f7d9 | ||
|
|
9aa09050da | ||
|
|
f331de4185 | ||
|
|
1ce067c854 | ||
|
|
e6d537f0f8 | ||
|
|
6a69a8d21a | ||
|
|
415cc09a06 | ||
|
|
fb482e133e | ||
|
|
c8134ce2ec | ||
|
|
a59c062dda | ||
|
|
fe604d3439 | ||
|
|
53ad8466ad | ||
|
|
9e3c844231 | ||
|
|
85a10e7c72 | ||
|
|
902dc5bdd1 | ||
|
|
666cbc9e47 | ||
|
|
745fae3f76 | ||
|
|
bb2c4d4c3f | ||
|
|
f8c8d6725c | ||
|
|
54747dc800 | ||
|
|
63b6c0cab4 | ||
|
|
92c85a0791 | ||
|
|
83f47bfe6e | ||
|
|
2f034e98c0 | ||
|
|
cb416c3583 | ||
|
|
584353a240 | ||
|
|
729456c2a0 | ||
|
|
a02a2e5332 | ||
|
|
78f0204d86 | ||
|
|
b76ef5ca80 | ||
|
|
788fc01cfb | ||
|
|
4dc9360b34 | ||
|
|
6c0e1b7f01 | ||
|
|
27b91642f2 | ||
|
|
0c7be4b2c7 | ||
|
|
e41ba71828 | ||
|
|
2b2b6b98f1 | ||
|
|
8f6b20abd1 | ||
|
|
21a69c4a61 | ||
|
|
e7b671283a | ||
|
|
d46a7a50b5 | ||
|
|
dfae4e0848 | ||
|
|
a0f7e924e5 | ||
|
|
fd2f3c7dbe | ||
|
|
da442dc02b | ||
|
|
eaea900100 | ||
|
|
449662f858 | ||
|
|
def2219f41 | ||
|
|
4670fc477d | ||
|
|
cea4572843 | ||
|
|
b769d4644a | ||
|
|
3d9b117a74 | ||
|
|
3b1a5f227e | ||
|
|
a66a2d936e | ||
|
|
8b5c334d47 | ||
|
|
5597cf6753 | ||
|
|
9d2d83d8d1 | ||
|
|
bc695479fa | ||
|
|
c0f7f2accd | ||
|
|
08309d6162 | ||
|
|
b217036ad0 | ||
|
|
a276652cbc | ||
|
|
39f643330a | ||
|
|
2967cc917c | ||
|
|
78d22b3165 | ||
|
|
989036bdf2 | ||
|
|
926e9ff92c | ||
|
|
4696567514 | ||
|
|
e153a30186 | ||
|
|
e8bbd3dace | ||
|
|
d2d1344858 | ||
|
|
6be828079d | ||
|
|
7a07a5c646 | ||
|
|
ee649ebeb9 | ||
|
|
67fe2a5a67 | ||
|
|
6ac193c139 | ||
|
|
b7492a6dfa | ||
|
|
224e86f673 | ||
|
|
f014e155d6 | ||
|
|
7aa37cd6cb | ||
|
|
b1cc09fcb6 | ||
|
|
4717293666 | ||
|
|
a80cd0720f | ||
|
|
e238676efc | ||
|
|
e1df231137 | ||
|
|
f40d10b35c | ||
|
|
ea20e5445e | ||
|
|
4a6f2dbdc3 | ||
|
|
11ff01bc61 | ||
|
|
2a292e6a82 | ||
|
|
dc11242b77 | ||
|
|
4ec8f5fc28 | ||
|
|
690f3ed87c | ||
|
|
04e8f6f2e3 | ||
|
|
e96ab86198 | ||
|
|
eae010a23b | ||
|
|
d9d829e37d | ||
|
|
53680fc774 | ||
|
|
46b8378297 | ||
|
|
a26b4f779e | ||
|
|
c2e8c87f3b | ||
|
|
c99e82bd8e | ||
|
|
1398e54896 | ||
|
|
2d93e5bb1c | ||
|
|
6b901d42f7 | ||
|
|
0cc8a968ed | ||
|
|
3f2914c6fa | ||
|
|
9e01786278 | ||
|
|
78ec625cd5 | ||
|
|
02855e3ac4 | ||
|
|
2fc65f135d | ||
|
|
88085ca5a6 | ||
|
|
fe26a82d66 | ||
|
|
e98678b1f7 | ||
|
|
ef2b4d785a | ||
|
|
b721f3e3ce | ||
|
|
13cc0fc08c | ||
|
|
65fe95d464 | ||
|
|
80a887b0d0 | ||
|
|
bed1915da4 | ||
|
|
65cde0af99 | ||
|
|
a0a2b8b265 | ||
|
|
ed01254c84 | ||
|
|
e03864ac03 | ||
|
|
83796c5aa4 | ||
|
|
0e329def1a | ||
|
|
27859cf183 | ||
|
|
5560e7ee3d | ||
|
|
72bab915b1 | ||
|
|
f5fefcdd55 | ||
|
|
160634ea38 | ||
|
|
50fb5a96d8 | ||
|
|
79c7ea16d8 | ||
|
|
a166db0ea1 | ||
|
|
2b905615d1 | ||
|
|
a18c1b5e0c | ||
|
|
c066043ceb | ||
|
|
41d64f1b7c | ||
|
|
36023fdc35 | ||
|
|
8437cf279d | ||
|
|
d2e19cf3c7 | ||
|
|
9a90be6e79 | ||
|
|
903a4c78e2 | ||
|
|
19049bfea8 | ||
|
|
0c4e92ebec | ||
|
|
aefe937adc | ||
|
|
63eda04815 | ||
|
|
18c7783942 | ||
|
|
6c17e1e9c5 | ||
|
|
955355460e | ||
|
|
51a110b9a3 | ||
|
|
43da6c3656 | ||
|
|
411c916a26 | ||
|
|
c0cc14ec99 | ||
|
|
4f8dd8844c | ||
|
|
36f8f43aad | ||
|
|
534d7f570e | ||
|
|
599e514afc | ||
|
|
42054827a2 | ||
|
|
bfe517ef75 | ||
|
|
c585f3455d | ||
|
|
fe1d3dd82b | ||
|
|
92d503335b | ||
|
|
782f93169d | ||
|
|
0c12177091 | ||
|
|
cc90ff97e3 | ||
|
|
525230cf2d | ||
|
|
2df9ef3fca | ||
|
|
9de1b6d9d2 | ||
|
|
94b096259a | ||
|
|
4e7011f12b | ||
|
|
ff123ddcb4 | ||
|
|
9d98fefdef | ||
|
|
573bddb1ae | ||
|
|
8386848e0e | ||
|
|
5ba0220a74 | ||
|
|
d24cadcf00 | ||
|
|
fbe53df424 | ||
|
|
eb0347073e | ||
|
|
45907bdcca | ||
|
|
b5b8aaf731 | ||
|
|
d4eb749729 | ||
|
|
3e09882b0c | ||
|
|
a443b57ead | ||
|
|
3a430b3586 | ||
|
|
f09f8ba4eb | ||
|
|
c6a1560a0f | ||
|
|
805f596f1f | ||
|
|
bcee601d4c | ||
|
|
ea009e802b | ||
|
|
e421eaaf1a | ||
|
|
997cd88db8 | ||
|
|
ccc8fbde05 | ||
|
|
0fdf7721a7 | ||
|
|
96f1863711 | ||
|
|
ea9c7543d9 | ||
|
|
b69a02c878 | ||
|
|
4d9c792a25 | ||
|
|
7a6992845a | ||
|
|
f2deb8f402 | ||
|
|
c067b162b9 | ||
|
|
f1415d7583 | ||
|
|
14f23e79f1 | ||
|
|
a5a55e207c | ||
|
|
990337e4f4 | ||
|
|
c35cce7b34 | ||
|
|
cb36e60af7 | ||
|
|
65baef92b1 | ||
|
|
c624db6833 | ||
|
|
8aed964f47 | ||
|
|
3874cb93e1 | ||
|
|
f966d7ab99 | ||
|
|
2079705626 | ||
|
|
e0a56d350b | ||
|
|
181aa4f43b | ||
|
|
302ba9be44 | ||
|
|
77422c8dda | ||
|
|
eead43e0d9 | ||
|
|
87927d04aa | ||
|
|
aa1b4b2785 | ||
|
|
a7f1d7181d | ||
|
|
c4a50efa43 | ||
|
|
b30f7d95e2 | ||
|
|
845b8aac1b | ||
|
|
d449469a99 | ||
|
|
776ae01c7b | ||
|
|
a9951fc624 | ||
|
|
d8dfcd9cf7 | ||
|
|
fac6744ead | ||
|
|
0a539d1328 | ||
|
|
3e137d1c0e | ||
|
|
8391556f8f | ||
|
|
365374e73e | ||
|
|
19a118c096 | ||
|
|
62a5505c9d | ||
|
|
60dcb66805 | ||
|
|
51e6306c19 | ||
|
|
683453f63a | ||
|
|
366e042c60 | ||
|
|
e599d96b7f | ||
|
|
6f3fde82ef | ||
|
|
8ba561b55b | ||
|
|
79ac8e8cd8 | ||
|
|
cb809156f2 | ||
|
|
d8aa4dde98 | ||
|
|
938fd759c1 | ||
|
|
2740f54331 | ||
|
|
6f929e48b8 | ||
|
|
308db7888a | ||
|
|
657a5c5416 | ||
|
|
d12f3921f9 | ||
|
|
601957ba2a | ||
|
|
e12ffb1a75 | ||
|
|
25543b363b | ||
|
|
3e8ab559b2 | ||
|
|
9059f3f60b | ||
|
|
aa4ce25bda | ||
|
|
5ecd9e0782 | ||
|
|
ba84cc7ea6 | ||
|
|
7edae77736 | ||
|
|
b5f414623e | ||
|
|
58c92c94f6 | ||
|
|
3f0509b0b9 | ||
|
|
33858d2679 | ||
|
|
5d3b4fab0b | ||
|
|
6f998cffe9 | ||
|
|
1f520b904f | ||
|
|
94c49deaf7 | ||
|
|
4360896634 | ||
|
|
8513edc118 | ||
|
|
6dc08ede91 | ||
|
|
8f05520c2f | ||
|
|
0c3878a8fc | ||
|
|
e0d9fa6e95 | ||
|
|
ef5f613b0b | ||
|
|
8617557084 | ||
|
|
55c0fe05cc | ||
|
|
bdaaa9643e | ||
|
|
883ab83c91 | ||
|
|
6df9a499ef | ||
|
|
2bbb6919b6 | ||
|
|
44e0102073 | ||
|
|
a772a2dd51 | ||
|
|
8cd812cf33 | ||
|
|
dbf30f4869 | ||
|
|
3b5ec52a06 | ||
|
|
740e39fb46 | ||
|
|
44fff4fc0a | ||
|
|
acc3a0c9d4 | ||
|
|
e9f7f9d027 | ||
|
|
3ff9bcf853 | ||
|
|
18dd011a84 | ||
|
|
5ccfd4e838 | ||
|
|
b0baad56e7 | ||
|
|
0732938d1d | ||
|
|
1df2d8da9b | ||
|
|
dfdc7567f5 | ||
|
|
3453b7f84c | ||
|
|
59137196c6 | ||
|
|
8d686da3fb | ||
|
|
10aa459ebd | ||
|
|
a3737624fe | ||
|
|
70dd7d8744 | ||
|
|
8d52a98504 | ||
|
|
994166c88f | ||
|
|
2a9252b53b | ||
|
|
e8ff2a36be | ||
|
|
9ac700b758 | ||
|
|
1bf994384d | ||
|
|
0258389b61 | ||
|
|
8491807987 | ||
|
|
e95d07fee1 | ||
|
|
7b0d07e116 | ||
|
|
5228ed8543 | ||
|
|
8f5550576f | ||
|
|
c51e4b5411 | ||
|
|
ef3918f50c | ||
|
|
2b29e5371d | ||
|
|
249815607e | ||
|
|
b9f9138ae4 | ||
|
|
00296bacf2 | ||
|
|
18e6771fcc | ||
|
|
0c8131ebb3 | ||
|
|
831f0209ae | ||
|
|
488fc2719f | ||
|
|
ba98d6dfef | ||
|
|
45d9b69191 | ||
|
|
5205c94c73 | ||
|
|
953bc6370a | ||
|
|
7ffd7b10f5 | ||
|
|
2a054bce6e | ||
|
|
de1ed66aaa | ||
|
|
caeeee9109 | ||
|
|
3c9368b05f | ||
|
|
e31567727a | ||
|
|
7b761c50d7 | ||
|
|
11306a3ce5 | ||
|
|
9d23d4df1f | ||
|
|
45c35d1d37 | ||
|
|
7b1c7cbcb2 | ||
|
|
01b4431627 | ||
|
|
70b478a4b7 | ||
|
|
6e7d227504 | ||
|
|
962afaf613 | ||
|
|
ad0ba5d3bf | ||
|
|
6c729deb77 | ||
|
|
0e887d8b28 | ||
|
|
8fdaf68707 | ||
|
|
0bbbf70e81 | ||
|
|
1342c306a3 | ||
|
|
8890ae4520 | ||
|
|
72d6fa5454 | ||
|
|
1f700a80bc | ||
|
|
d9a25c88e7 | ||
|
|
e060b80b67 | ||
|
|
45687e665d | ||
|
|
5a3dffbc98 | ||
|
|
9e932f025f | ||
|
|
5ea729d0d0 | ||
|
|
67b6c52031 | ||
|
|
8b9c26c12b | ||
|
|
bede7d3fc9 | ||
|
|
cf2d4b890a | ||
|
|
3aa05efe9c | ||
|
|
ac00b513a8 | ||
|
|
7fb4f6de65 | ||
|
|
26251a2158 | ||
|
|
4a0b1f8f10 | ||
|
|
d6cce4a11b | ||
|
|
2ad79ea3d1 | ||
|
|
82ce761b88 | ||
|
|
d1241a6997 | ||
|
|
eb28720cd2 | ||
|
|
436a36a704 | ||
|
|
c2298b2ae0 | ||
|
|
9bc1431291 | ||
|
|
695a57153a | ||
|
|
b19ce01e2e | ||
|
|
d0c74b73dc | ||
|
|
673fce5054 | ||
|
|
9195f7ed31 | ||
|
|
baf97b205f | ||
|
|
13da03396f | ||
|
|
52846e3bf2 | ||
|
|
164c43e2e5 | ||
|
|
3af93df990 | ||
|
|
6026d27b18 | ||
|
|
ba8786c4fe | ||
|
|
5650349868 | ||
|
|
8bd3c32a65 | ||
|
|
07623acf41 | ||
|
|
446629b9f8 | ||
|
|
21dca42e33 | ||
|
|
7c5c9fc8be | ||
|
|
b2262ad4b8 | ||
|
|
4f7aba1e4b | ||
|
|
2bfbc68df8 | ||
|
|
682ae2ed59 | ||
|
|
a13705c1fe | ||
|
|
e4f4ba46f5 | ||
|
|
1f4b343a2e | ||
|
|
f4e01f42c5 | ||
|
|
7416ea1a54 | ||
|
|
b9593b7b4c | ||
|
|
43d7725522 | ||
|
|
d8d3a392b2 | ||
|
|
5a36e72616 | ||
|
|
e9bfe72914 | ||
|
|
db23f28388 | ||
|
|
46bd9a5324 | ||
|
|
d225b6d454 | ||
|
|
17fb991744 | ||
|
|
1035d413de | ||
|
|
9bbccb72e4 | ||
|
|
4b525256fb | ||
|
|
960059e307 | ||
|
|
0941627527 | ||
|
|
efea8c451b | ||
|
|
d9811f4ff1 | ||
|
|
11e6713f20 | ||
|
|
0d37538778 | ||
|
|
c88f8bb277 | ||
|
|
cd8a8ba310 | ||
|
|
9cb81c5fb8 | ||
|
|
e2d3dc1258 | ||
|
|
3c51397be8 | ||
|
|
84d51bf653 | ||
|
|
70c541b06f | ||
|
|
79a7095739 | ||
|
|
cf7fbf0b83 | ||
|
|
f1bf807b67 | ||
|
|
f02581d20a | ||
|
|
03450fc4f7 | ||
|
|
5e0eaa529f | ||
|
|
56184370a7 | ||
|
|
6fdc672dc4 | ||
|
|
ec82a24910 | ||
|
|
06157a9e5c | ||
|
|
a53022bac0 | ||
|
|
896c775fef | ||
|
|
f907d689e5 | ||
|
|
90a9850034 | ||
|
|
4418d348c5 | ||
|
|
7ce93da521 | ||
|
|
aeb08616b5 | ||
|
|
a10df3a133 | ||
|
|
c4039f5663 | ||
|
|
30df4a257a | ||
|
|
6f0df065ad | ||
|
|
8cfc5567d1 | ||
|
|
32defc6833 | ||
|
|
4485cf33df | ||
|
|
d7638ea764 | ||
|
|
d334a472ce | ||
|
|
19672dba39 | ||
|
|
24358eeb51 | ||
|
|
c1a823cd42 | ||
|
|
849c4982a8 | ||
|
|
032d6a1ae1 | ||
|
|
b012c48e62 | ||
|
|
76aa0f70aa | ||
|
|
1c3c525d2b | ||
|
|
9042b16df4 | ||
|
|
1f9198964b | ||
|
|
698513ea84 | ||
|
|
0cb68d9b5d | ||
|
|
221a0942ab | ||
|
|
c83fcc4602 | ||
|
|
b51abc68a8 | ||
|
|
9040c32f52 | ||
|
|
dc81c7244a | ||
|
|
62debd3df4 | ||
|
|
a048cf0f23 | ||
|
|
50ed79c0b3 | ||
|
|
b6963c7cab | ||
|
|
9f5af15987 | ||
|
|
5119048f33 | ||
|
|
090f45092c | ||
|
|
925e36e33b | ||
|
|
720b64ff90 | ||
|
|
4cd9f11f0b | ||
|
|
1b54504165 | ||
|
|
080e514527 | ||
|
|
392ed8b517 | ||
|
|
546701894d | ||
|
|
b90139aee4 | ||
|
|
5d39b554e0 | ||
|
|
51b9ab3661 | ||
|
|
b58672b8ec | ||
|
|
4148b57819 | ||
|
|
8a9f0ddd24 | ||
|
|
4ccc377f1c | ||
|
|
dc56d18595 | ||
|
|
ff78f68443 | ||
|
|
5b52b070d9 | ||
|
|
8f28becd6c | ||
|
|
14212a744a | ||
|
|
cb0af54ab4 | ||
|
|
b6b737a0cd | ||
|
|
092ec1a8f0 | ||
|
|
9476d8bbcd | ||
|
|
72e4a6ccc7 | ||
|
|
73d2c83d8e | ||
|
|
540b315213 | ||
|
|
9594014358 | ||
|
|
d3e781607d | ||
|
|
e9d6874ff5 | ||
|
|
729b43cd54 | ||
|
|
5278060aaa | ||
|
|
d25a1e8463 | ||
|
|
24e260dc0d | ||
|
|
ea6a010c5e | ||
|
|
07715fd541 | ||
|
|
6b9e0e60c5 | ||
|
|
1040b041a4 | ||
|
|
914dcced2b | ||
|
|
520d2bf0a8 | ||
|
|
886a09553f | ||
|
|
9436fa50b8 | ||
|
|
feae293d17 | ||
|
|
8eba025e02 | ||
|
|
060f5dfd6c | ||
|
|
e3e3bb2731 | ||
|
|
1082dd5aa4 | ||
|
|
aaba37325b | ||
|
|
fe225efde5 | ||
|
|
1726a45738 | ||
|
|
09f3ebec80 | ||
|
|
f8a4534496 | ||
|
|
299833b974 | ||
|
|
317a1cd8ca | ||
|
|
81d7ecde04 | ||
|
|
1377769eff | ||
|
|
1cbde75953 | ||
|
|
72d16e22be | ||
|
|
8fa6721a26 | ||
|
|
aeb2355d75 | ||
|
|
81a3adb483 | ||
|
|
8298a22023 | ||
|
|
c3612ec9a6 | ||
|
|
c05f158663 | ||
|
|
671851f345 | ||
|
|
1611429d83 | ||
|
|
a8593078ad | ||
|
|
6165c25976 | ||
|
|
47598a9d7a | ||
|
|
09c727e91a | ||
|
|
0619557f05 | ||
|
|
aa5a9c6c2d | ||
|
|
e3ad81926e | ||
|
|
37abd6d5b8 | ||
|
|
5a7499c80e | ||
|
|
ce3bb23b8c | ||
|
|
845d5b2351 | ||
|
|
08ee361c9c | ||
|
|
c6e6a4bd7d | ||
|
|
85b571594c | ||
|
|
5088c94db5 | ||
|
|
2dc9e9e04c | ||
|
|
2752c641ed | ||
|
|
4c0b6bff9d | ||
|
|
5acebc3e44 | ||
|
|
1e8c065fdb | ||
|
|
b35775b3e0 | ||
|
|
0693853c0a | ||
|
|
6994d12eb6 | ||
|
|
dc0dda35fc | ||
|
|
085fc2a764 | ||
|
|
7ecae9e3a2 | ||
|
|
61d687882f | ||
|
|
354eed23b9 | ||
|
|
99996613bc | ||
|
|
c6e7b1d68a | ||
|
|
69e9823640 | ||
|
|
6e74d02e95 | ||
|
|
397d3073c6 | ||
|
|
ecba921352 | ||
|
|
bea36fdcb5 | ||
|
|
0379e0ee6d | ||
|
|
787a48a795 | ||
|
|
ce257fcc95 | ||
|
|
becc50d2b8 | ||
|
|
673be6056c | ||
|
|
5c7b19527d | ||
|
|
4304099d3a | ||
|
|
5911968469 | ||
|
|
6afde15a1d | ||
|
|
ab578f499c | ||
|
|
e78c3bc6aa | ||
|
|
6394a8ee76 | ||
|
|
5f4e62824f | ||
|
|
f1966f42de | ||
|
|
704039afc2 | ||
|
|
b1c9b27f17 | ||
|
|
3a1c0a707a | ||
|
|
781c28044a | ||
|
|
76346a435a | ||
|
|
a4ebe3532b | ||
|
|
189c8c5a2a | ||
|
|
c1c50fcdb0 | ||
|
|
aad91c32d1 | ||
|
|
b80a84822e | ||
|
|
3e4f86d5fe | ||
|
|
3cb9fa6926 | ||
|
|
900fe003d4 | ||
|
|
3c923f7a20 | ||
|
|
6d95c85719 | ||
|
|
5a0bdb6358 | ||
|
|
49f8d7ac56 | ||
|
|
fd99d88510 | ||
|
|
29f37bbe43 | ||
|
|
1567dd6163 | ||
|
|
297d0b7466 | ||
|
|
7db378a8c8 | ||
|
|
3f5c73ca26 | ||
|
|
53f7ddcb82 | ||
|
|
1f54a40147 | ||
|
|
4c3cdaf593 | ||
|
|
af00eeaf2a | ||
|
|
ed5629f7cf | ||
|
|
88d1854b0d | ||
|
|
328cb3a4dc | ||
|
|
a1c83ebb10 | ||
|
|
d440a78c7b | ||
|
|
6e643d7cda | ||
|
|
0f705bd755 | ||
|
|
f436e44233 | ||
|
|
29f6c5907c | ||
|
|
a4d5015875 | ||
|
|
e8aa282a3a | ||
|
|
44dc55822d | ||
|
|
473bc16384 | ||
|
|
8984a1baf6 | ||
|
|
8fda96eabf | ||
|
|
5110c5d248 | ||
|
|
d23bdee6ed | ||
|
|
2f2ecbbeb0 | ||
|
|
867fe28c5f | ||
|
|
958cdc627a | ||
|
|
473aa9c429 | ||
|
|
846dd24dde | ||
|
|
c01823024d | ||
|
|
1cba327f24 | ||
|
|
c973edee05 | ||
|
|
6744926708 | ||
|
|
a5f040d69d | ||
|
|
0507f25e86 | ||
|
|
f782f18f04 | ||
|
|
ddb58f148d | ||
|
|
75904cf88c | ||
|
|
522deec88b | ||
|
|
4c07d608c5 | ||
|
|
c3490ac819 | ||
|
|
0ada1f2e46 | ||
|
|
6d7493c6e5 | ||
|
|
3306d8a276 | ||
|
|
d5b607eb72 | ||
|
|
af22c74602 | ||
|
|
1822850835 | ||
|
|
f185b9c30d | ||
|
|
d6c39e05f9 | ||
|
|
d7abef33a6 | ||
|
|
a0f6712c57 | ||
|
|
e81acee86b | ||
|
|
bbc9080cfa | ||
|
|
2095280783 | ||
|
|
d2b2e9a0d9 | ||
|
|
e62adf9131 | ||
|
|
4f22a869b8 | ||
|
|
8cf5868a30 | ||
|
|
f8d2b47006 | ||
|
|
71f0f53cae | ||
|
|
5b1fe105ba | ||
|
|
7f447ac21f | ||
|
|
425c7cd390 | ||
|
|
7f72143ee7 | ||
|
|
e743500d6c | ||
|
|
77e3952849 | ||
|
|
21dab1bf50 | ||
|
|
4e9aa726c6 | ||
|
|
004babb572 | ||
|
|
256c048598 | ||
|
|
59b884f4e4 | ||
|
|
45ff535d31 | ||
|
|
4cd8c53645 | ||
|
|
b856ef4ea6 | ||
|
|
ea3d83962f | ||
|
|
1d79076e65 | ||
|
|
1e6bae6801 | ||
|
|
6cda51ebbe | ||
|
|
e4c4c1b964 | ||
|
|
939c8c6d0e | ||
|
|
33c3963f66 | ||
|
|
88bfaa532d | ||
|
|
66e321ebea | ||
|
|
8d2838e928 | ||
|
|
98d896eb81 | ||
|
|
62bd56e70d | ||
|
|
bbc7e0f648 | ||
|
|
534c8e0bc3 | ||
|
|
1f9897e551 | ||
|
|
eba54c8da3 | ||
|
|
e47ac5b02d | ||
|
|
9d134f8171 | ||
|
|
1ec477b5bc | ||
|
|
022f203a2e | ||
|
|
191f21bf50 | ||
|
|
98c4b37664 | ||
|
|
2f2b40ca53 | ||
|
|
8a8be30657 | ||
|
|
0c0aafb956 | ||
|
|
c0bca5b923 | ||
|
|
55ea356efd | ||
|
|
fbcd357b69 | ||
|
|
41db619e28 | ||
|
|
1de8b11d75 | ||
|
|
b85f082d03 | ||
|
|
c2f08b47aa | ||
|
|
329784c9a7 | ||
|
|
1d357aab0a | ||
|
|
fe6deb559b | ||
|
|
591ef4d1f9 | ||
|
|
6a8a991f42 | ||
|
|
87161cb97a | ||
|
|
a28b667b38 | ||
|
|
62c8b4b9e9 | ||
|
|
bc0d5e2e7e | ||
|
|
a66ea60ae7 | ||
|
|
80f908353f | ||
|
|
a3a8ad87d3 | ||
|
|
ea52a7a9ec | ||
|
|
972042645c | ||
|
|
e01c8d4e13 | ||
|
|
351373aea5 | ||
|
|
287680df87 | ||
|
|
aa96a98722 | ||
|
|
58aa231cd2 | ||
|
|
d0a59e9d6f | ||
|
|
972c278356 | ||
|
|
d3b236107b | ||
|
|
ddd359afe0 | ||
|
|
0278777ff4 | ||
|
|
c8b703778b | ||
|
|
a0d49f8c29 | ||
|
|
93f9a318b0 | ||
|
|
bc6679505d | ||
|
|
5698e1a4fb | ||
|
|
61c39a8919 | ||
|
|
ae2e8b6abd | ||
|
|
e1bce30ee3 | ||
|
|
44da884057 | ||
|
|
7f9f05ae0e | ||
|
|
4638d173b6 | ||
|
|
43bc3cee06 | ||
|
|
2db68559d5 | ||
|
|
122b07b757 | ||
|
|
d6760ca4b9 | ||
|
|
fe036e75a3 | ||
|
|
a574e77f0a | ||
|
|
b4c885067d | ||
|
|
200fb9d9ee | ||
|
|
ec06fdcda6 | ||
|
|
fb31cc7268 | ||
|
|
afdbf2ac0b | ||
|
|
4197230ffd | ||
|
|
952e22367e | ||
|
|
a497660c64 | ||
|
|
bd3f4e08b2 | ||
|
|
c2e5aba0e4 | ||
|
|
729cf2c033 | ||
|
|
2633bd46c3 | ||
|
|
f6430d421e | ||
|
|
1045290320 | ||
|
|
0416bb20b3 | ||
|
|
cb7223dee1 | ||
|
|
59b535b0d8 | ||
|
|
6b9d2c19a7 | ||
|
|
3d7fbefa24 | ||
|
|
24311c2e71 | ||
|
|
93db8cc163 | ||
|
|
bdd833e05b | ||
|
|
64bcb9b4c3 | ||
|
|
6f2cf36ba6 | ||
|
|
4828af7130 | ||
|
|
0d0aa7c9a0 | ||
|
|
f0c962fde0 | ||
|
|
a04197f145 | ||
|
|
530e9b05ef | ||
|
|
5276b5f9f7 | ||
|
|
9a8f5f7186 | ||
|
|
7de2b3567d | ||
|
|
2a53fd6f13 | ||
|
|
1092fd4198 | ||
|
|
dd5619c1f9 | ||
|
|
06cffc101f | ||
|
|
5f17dae777 | ||
|
|
001a8a276f | ||
|
|
16986f0f56 | ||
|
|
36ff2808bd | ||
|
|
b566e10847 | ||
|
|
1b4fbf17a8 | ||
|
|
1475b1a299 | ||
|
|
147c5455ff | ||
|
|
73bfd9b66c | ||
|
|
f5fa061392 | ||
|
|
71b50171de | ||
|
|
a172caba24 | ||
|
|
ab39c3bbdb | ||
|
|
29733cc474 | ||
|
|
00a358cfb6 | ||
|
|
000475884d | ||
|
|
49b2cda0c2 | ||
|
|
fdf229400a | ||
|
|
c79d485d69 | ||
|
|
3f9aa621d1 | ||
|
|
c94c00d933 | ||
|
|
e540855bf9 | ||
|
|
e3d55f4e3d | ||
|
|
988fc92456 | ||
|
|
c02b153ef1 | ||
|
|
70ca4893ba | ||
|
|
4e15d3779c | ||
|
|
f924a18d07 | ||
|
|
bce1ec1c66 | ||
|
|
7c4347ad9b | ||
|
|
820c594c1e | ||
|
|
5c2d319b3a | ||
|
|
ff62cc55c2 | ||
|
|
dee872fec2 | ||
|
|
87b670ca4e | ||
|
|
60c4c2f526 | ||
|
|
6fd03f826c | ||
|
|
365cdb9fef | ||
|
|
4342602202 | ||
|
|
a168c10938 | ||
|
|
09da6f870a | ||
|
|
8a4b334d20 | ||
|
|
4f6916a2df | ||
|
|
14a9c94944 | ||
|
|
6ad0fda364 | ||
|
|
491c124ac1 | ||
|
|
81cb7b4f84 | ||
|
|
90c91c2b16 | ||
|
|
161d2810a3 | ||
|
|
9c0dae8d9a | ||
|
|
6375be4d2c | ||
|
|
64234815cc | ||
|
|
b56d4d1ca3 | ||
|
|
8d31b287f2 | ||
|
|
8e59d905ba | ||
|
|
028661f9f8 | ||
|
|
f6189c6d8a | ||
|
|
ee677ced24 | ||
|
|
5f5c142d03 | ||
|
|
2a7fe455ad | ||
|
|
047469de5b | ||
|
|
7a61a68f00 | ||
|
|
50f71390f8 | ||
|
|
fba7bb68fe | ||
|
|
2f6749bf5e | ||
|
|
9253c6dd7b | ||
|
|
e23ad8239b | ||
|
|
2f9e624c31 | ||
|
|
a336b50e0f | ||
|
|
5bc4a96e77 | ||
|
|
113ba8223c | ||
|
|
a760150d75 | ||
|
|
42a52dc606 | ||
|
|
b0c45c115e | ||
|
|
6a427a04ff | ||
|
|
1959c009fd | ||
|
|
35f5bdd483 | ||
|
|
ff422bae19 | ||
|
|
f2e4d5cc1b | ||
|
|
5fba69cad3 | ||
|
|
a1385956aa | ||
|
|
9493cbc6ff | ||
|
|
0762841ef0 | ||
|
|
e94fb73fd2 | ||
|
|
6cb5f738d4 | ||
|
|
1b66d6fe4d | ||
|
|
3a9511a6b2 | ||
|
|
70cfcda727 | ||
|
|
ef7ab11078 | ||
|
|
14ad9618d3 | ||
|
|
41ce3d862c | ||
|
|
2ae9e8bb6f | ||
|
|
8ebdaee97f | ||
|
|
9dab0f0c03 | ||
|
|
3144a6b5fd | ||
|
|
f6ed045b8f | ||
|
|
b31c29b440 | ||
|
|
0bf4181056 | ||
|
|
ff3fc84563 | ||
|
|
644af53193 | ||
|
|
b52eb24e85 | ||
|
|
b0ee04fab2 | ||
|
|
0b01f5ec1c | ||
|
|
310a2f5443 | ||
|
|
9c7de1a8fe | ||
|
|
2ff2d55f25 | ||
|
|
3d5e7be6b6 | ||
|
|
4bce655cb6 | ||
|
|
f2aa01d23c | ||
|
|
37907ed7f6 | ||
|
|
17d34ae443 | ||
|
|
5e442d43aa | ||
|
|
3594c81b17 | ||
|
|
221c830d60 | ||
|
|
962c2db587 | ||
|
|
e22d3367ba | ||
|
|
27df815529 | ||
|
|
64ad14ae80 | ||
|
|
3de09dc8db | ||
|
|
170aede49f | ||
|
|
9ab740e53b | ||
|
|
ddd4a806e1 | ||
|
|
5b4b427589 | ||
|
|
67900764f0 | ||
|
|
df3995f0bb | ||
|
|
96278eb6d4 | ||
|
|
b012abbffb | ||
|
|
cd52110e95 | ||
|
|
eba00e0e26 | ||
|
|
baab38c7f6 | ||
|
|
539530bcb9 | ||
|
|
829cdec53c | ||
|
|
1bbe89f962 | ||
|
|
1ae9724d34 | ||
|
|
d71142a253 | ||
|
|
ca0437d765 | ||
|
|
7e4619c2ae | ||
|
|
65dd9e26e9 | ||
|
|
fe788ca5dc | ||
|
|
4e3fd87481 | ||
|
|
6244663e80 | ||
|
|
3bce988e12 | ||
|
|
0fcc9e112a | ||
|
|
d083ae6d0e | ||
|
|
ddffc72e76 | ||
|
|
20d22fa036 | ||
|
|
ccb923ecc4 | ||
|
|
90f98c69c5 | ||
|
|
2f273777b2 | ||
|
|
3936960caf | ||
|
|
e32262a3b3 | ||
|
|
bc9d7f7c2a | ||
|
|
71fe870b1d | ||
|
|
28a0456fa7 | ||
|
|
ad7e00add5 | ||
|
|
6e5749063c | ||
|
|
048de253a9 | ||
|
|
c6c9578691 | ||
|
|
b052c04749 | ||
|
|
5085255f61 | ||
|
|
cd306135ad | ||
|
|
fbb9cac178 | ||
|
|
291210aadf | ||
|
|
458a9b9907 | ||
|
|
d210feab0d | ||
|
|
c3aaf78161 | ||
|
|
a86c7c6c1e | ||
|
|
8f79204fbc | ||
|
|
c21823c84e | ||
|
|
c40f64a193 | ||
|
|
f42cd221cc | ||
|
|
a8dc2a07db | ||
|
|
93e27f318d | ||
|
|
7ecb3ccf46 | ||
|
|
1dd48aa3f1 | ||
|
|
9ee7c6809a | ||
|
|
4eec46012a | ||
|
|
455edff025 | ||
|
|
79a43fe897 | ||
|
|
34306f023c | ||
|
|
e42baf816c | ||
|
|
f4cf76bc8f | ||
|
|
d7ef57a24e | ||
|
|
a349a3390c | ||
|
|
eae6e6ed8d | ||
|
|
14d87875ae | ||
|
|
62d997c85a | ||
|
|
02f37b2eeb | ||
|
|
636e6b82be | ||
|
|
72c544a512 | ||
|
|
97c7a4db17 | ||
|
|
aa8b4881ce | ||
|
|
c6d37a4281 | ||
|
|
05b269c0cf | ||
|
|
07d14cee67 | ||
|
|
70fb35bd25 | ||
|
|
574f4f90da | ||
|
|
6a951e1325 | ||
|
|
4a1abadd09 | ||
|
|
84bd0af02e | ||
|
|
115b838d3c | ||
|
|
13032e726b | ||
|
|
cf6efbaa2d | ||
|
|
580db415d6 | ||
|
|
30b2d1d913 | ||
|
|
510b2bcdd5 | ||
|
|
30856325be | ||
|
|
a5ab34b707 | ||
|
|
90ee139265 | ||
|
|
1e298edbdd | ||
|
|
925afb70c3 | ||
|
|
c399b850c5 | ||
|
|
8cf03e3ee3 | ||
|
|
e6ba1fc61b | ||
|
|
a2a434d6fd | ||
|
|
fe00182efd | ||
|
|
b00fcc25ea | ||
|
|
e9624ab6d6 | ||
|
|
c2d129aaa6 | ||
|
|
6b3b7d6945 | ||
|
|
1889b840b1 | ||
|
|
bfb1a4ef23 | ||
|
|
f178f31248 | ||
|
|
9c13832307 | ||
|
|
1c3f87165e | ||
|
|
c6ce339d40 | ||
|
|
5a90b00e19 | ||
|
|
e6bf8b5321 | ||
|
|
156e493a90 | ||
|
|
2cf073495c | ||
|
|
43b193e965 | ||
|
|
b4b8dfb217 | ||
|
|
99051af886 | ||
|
|
768926fec3 | ||
|
|
a73042abc1 | ||
|
|
da36e3c1fa | ||
|
|
0024e3e74d | ||
|
|
9b14caf300 | ||
|
|
adee153190 | ||
|
|
c476cd7f25 | ||
|
|
d4da6b02a8 | ||
|
|
1d3f651846 | ||
|
|
d6af0ffc95 | ||
|
|
c1ba96d395 | ||
|
|
52f53e3410 | ||
|
|
aba4875cf3 | ||
|
|
f5057c2ac7 | ||
|
|
cfd5558765 | ||
|
|
77bbeb6de0 | ||
|
|
bf3e22bf4c | ||
|
|
a5596ac8f6 | ||
|
|
a3dddfa7f8 | ||
|
|
922abe8ba3 | ||
|
|
9b85f8673c | ||
|
|
b8e0bf92c2 | ||
|
|
05c7adbfee | ||
|
|
4081802dc8 | ||
|
|
45fb1cd801 | ||
|
|
50ed4a6988 | ||
|
|
96997e95a0 | ||
|
|
9029a64a19 | ||
|
|
cb6c9dd374 | ||
|
|
5b1e9d3f16 | ||
|
|
ceb1f954ff | ||
|
|
f67e4f953f | ||
|
|
76c071da14 | ||
|
|
c8dafae31d | ||
|
|
1924056c02 | ||
|
|
257dd22345 | ||
|
|
4211259874 | ||
|
|
9fa7d0182d | ||
|
|
8a00736c8f | ||
|
|
f1fd6b6d8b | ||
|
|
b1adad5866 | ||
|
|
f8aaa21b39 | ||
|
|
6b207e29fc | ||
|
|
4effb7cfdd | ||
|
|
83f48ac009 | ||
|
|
6788612ab5 | ||
|
|
8329c38894 | ||
|
|
5e96f69c52 | ||
|
|
f4c6b4f08d | ||
|
|
95fef77042 | ||
|
|
9814f44ead | ||
|
|
13189c6c6c | ||
|
|
aed16dfec6 | ||
|
|
3167399da9 | ||
|
|
c6b77fe861 | ||
|
|
aa1e4ecb7d | ||
|
|
1b677770b6 | ||
|
|
c707f20b3f | ||
|
|
c368e065b6 | ||
|
|
90eab0573f | ||
|
|
35d7286eec | ||
|
|
b68fe58a23 | ||
|
|
ea133a96cd | ||
|
|
69e48c77a9 | ||
|
|
606fb38ae6 | ||
|
|
b29955d191 | ||
|
|
7539fb3699 | ||
|
|
2d8911947a | ||
|
|
2044042973 | ||
|
|
dd02f890c2 | ||
|
|
45ca2eaaca | ||
|
|
aaf535c33f | ||
|
|
e9c6da2c11 | ||
|
|
e2c8efe29f | ||
|
|
e76b789eb7 | ||
|
|
75d1431e50 | ||
|
|
8a9da8a3ae | ||
|
|
3b718b0461 | ||
|
|
65b0d1fc23 | ||
|
|
c56ed37f7a | ||
|
|
340754d062 | ||
|
|
db85c34e61 | ||
|
|
807995fe8b | ||
|
|
111120edaa | ||
|
|
0bac8d6ae3 | ||
|
|
2ba17d8d5b | ||
|
|
a61633194d | ||
|
|
caa86bb931 | ||
|
|
cfe08bc542 | ||
|
|
4e55742219 | ||
|
|
f98ed62045 | ||
|
|
03653fb653 | ||
|
|
240a89da2c | ||
|
|
cfacd05578 | ||
|
|
c0ab5f955d | ||
|
|
f2346c5709 | ||
|
|
798bfc964c | ||
|
|
2af9014962 | ||
|
|
f8759278bc | ||
|
|
abed1b0645 | ||
|
|
8999fc8fd6 | ||
|
|
a1f9db4114 | ||
|
|
2336f1dc79 | ||
|
|
335e177578 | ||
|
|
a4434b16de | ||
|
|
9b3624e818 | ||
|
|
120a95f94d | ||
|
|
db0a658be2 | ||
|
|
822a8afcb1 | ||
|
|
eed371130f | ||
|
|
dd19c1040c | ||
|
|
54130e5ee7 | ||
|
|
827128d048 | ||
|
|
26c18562c4 | ||
|
|
0a847c8427 | ||
|
|
27a976fc53 | ||
|
|
73a3a881ca | ||
|
|
f07545285b | ||
|
|
4d02883a48 | ||
|
|
4eb9f0a0a4 | ||
|
|
1f630181d7 | ||
|
|
71a9b79527 | ||
|
|
b32d098d3b | ||
|
|
9118c1d64f | ||
|
|
8e4f7b0f08 | ||
|
|
3acc0592b4 | ||
|
|
dc5e24201c | ||
|
|
eda8f9ac86 | ||
|
|
ed19c9c534 | ||
|
|
c0ee0195e9 | ||
|
|
ffa35bed94 | ||
|
|
9442be13f1 | ||
|
|
a017803429 | ||
|
|
951e88f1c8 | ||
|
|
de93247c5c | ||
|
|
06038bc105 | ||
|
|
43c5975524 | ||
|
|
891f183f80 | ||
|
|
c126c28fa3 | ||
|
|
fc99e46e0f | ||
|
|
9543e10241 | ||
|
|
327bc47017 | ||
|
|
96ccc5d4f5 | ||
|
|
eef2b4eb58 | ||
|
|
26346c8acb | ||
|
|
565e77ef6d | ||
|
|
84506a9340 | ||
|
|
25298012f9 | ||
|
|
236e2f6d48 | ||
|
|
483283fdd1 | ||
|
|
776c2f38f8 | ||
|
|
c20cc09959 | ||
|
|
ce7d3f0324 | ||
|
|
55e85dbd74 | ||
|
|
4c6f6d8b1c | ||
|
|
651381c9d7 | ||
|
|
146af5cf2d | ||
|
|
49a7c80423 | ||
|
|
e770eb147a | ||
|
|
a08802df0a | ||
|
|
61eba87de6 | ||
|
|
0e0a56ac38 | ||
|
|
36e6c2fa25 | ||
|
|
0c157eee69 | ||
|
|
ba2ac37f6c | ||
|
|
9a29db8c62 | ||
|
|
212ec834c8 | ||
|
|
bd70d80f81 | ||
|
|
55e2e3463d | ||
|
|
2e16eba739 | ||
|
|
35bf66ccf4 | ||
|
|
ec4679d85c | ||
|
|
15c4b0e5eb | ||
|
|
5f170f0953 | ||
|
|
07a1e9311b | ||
|
|
7d1274af4b | ||
|
|
9d096aed5d | ||
|
|
8477ad810a | ||
|
|
60e3fb6f45 | ||
|
|
7efb9ec1de | ||
|
|
70c0a4b9e6 | ||
|
|
d9b3474846 | ||
|
|
97cb7fc2eb | ||
|
|
6394612630 | ||
|
|
a78df50826 | ||
|
|
59c1948e14 | ||
|
|
e92fa3d615 | ||
|
|
faee5d0276 | ||
|
|
f2b1e7becc | ||
|
|
5352d55589 | ||
|
|
75386e55af | ||
|
|
fe2a28d013 | ||
|
|
aa2e07d163 | ||
|
|
23c1c41415 | ||
|
|
8be6988e5b | ||
|
|
262ccc2f11 | ||
|
|
09c3952a0a | ||
|
|
ea9c4df4bc | ||
|
|
43c95c24fe | ||
|
|
21a19dcf89 | ||
|
|
2b6cc3e52d | ||
|
|
f639704d6d | ||
|
|
b93995081e | ||
|
|
0dc68b830c | ||
|
|
5521b90aec | ||
|
|
7f0a13b434 | ||
|
|
c0e2445439 | ||
|
|
6037b87b52 | ||
|
|
b80c5d43e9 | ||
|
|
ed258e624d | ||
|
|
e1fd87b251 | ||
|
|
092cf6be4f | ||
|
|
a4286ea2de | ||
|
|
7ada2de54c | ||
|
|
0f01f513eb | ||
|
|
4bebcec778 | ||
|
|
6d2bf8402b | ||
|
|
674f99d738 | ||
|
|
f12c2d3a7c | ||
|
|
8748b1e122 | ||
|
|
b6e4206772 | ||
|
|
2c6224d45e | ||
|
|
a0c764d87c | ||
|
|
a1f6278711 | ||
|
|
3ca45f4eef | ||
|
|
07ff46b98e | ||
|
|
c73d3fd96b | ||
|
|
e8594d05cb | ||
|
|
253db597bd | ||
|
|
8058276990 | ||
|
|
1e3f704ffd | ||
|
|
871d470c71 | ||
|
|
fd442bc08c | ||
|
|
b93499e373 | ||
|
|
0a2ddc696b | ||
|
|
d8f4020fa8 | ||
|
|
cfbf2c3bed | ||
|
|
3aa41ed16f | ||
|
|
6dae186ed6 | ||
|
|
9b3f0d84a8 | ||
|
|
ce1f7280c7 | ||
|
|
612ef7ef1a | ||
|
|
8800303766 | ||
|
|
5dfcc6e851 | ||
|
|
2d5703d9d9 | ||
|
|
796a4753c9 | ||
|
|
69cbeaaa1f | ||
|
|
10e37a2f8e | ||
|
|
416635020c | ||
|
|
36e9810f43 | ||
|
|
ecd3699620 | ||
|
|
cb63d3689d | ||
|
|
d69e7ae872 | ||
|
|
33dabab5a6 | ||
|
|
c8dec26d15 | ||
|
|
cce77d00ff | ||
|
|
7853d457a1 | ||
|
|
fd9318c127 | ||
|
|
8bd9f6cb4a | ||
|
|
c3aeb82137 | ||
|
|
322d4ab8a1 | ||
|
|
1fa6d61468 | ||
|
|
bf15621d24 | ||
|
|
39ce0abfe5 | ||
|
|
5ee754f82f | ||
|
|
ff7ffcbacb | ||
|
|
0d02b443e7 | ||
|
|
4ddae3d3ed | ||
|
|
1194a3a231 | ||
|
|
612cfc5bfc | ||
|
|
0340fcd8bf | ||
|
|
4bb4a2836c | ||
|
|
8d9da9f6b2 | ||
|
|
faf306ab83 | ||
|
|
fcaa13e4c4 | ||
|
|
4987cc92a1 | ||
|
|
fe9ad58989 | ||
|
|
95470804f1 | ||
|
|
300e2aabba | ||
|
|
f9f917f007 | ||
|
|
dbb49cac6c | ||
|
|
5540c1855f | ||
|
|
7d64e08093 | ||
|
|
4dafd8c3ff | ||
|
|
b6f65c40cf | ||
|
|
07e61cd1d3 | ||
|
|
c12c496058 | ||
|
|
4a5db41302 | ||
|
|
21f269593a | ||
|
|
56a14ecd77 | ||
|
|
a2c770d798 | ||
|
|
31351837a7 | ||
|
|
bc9a0f749b | ||
|
|
e8d590c622 | ||
|
|
5cb7314b56 | ||
|
|
b724e728d9 | ||
|
|
c686014204 | ||
|
|
b6534fd91d | ||
|
|
5a964a1dd5 | ||
|
|
1d290e97b8 | ||
|
|
9f68cdbd6e | ||
|
|
bb3269646d | ||
|
|
abba89bcad | ||
|
|
352642c93a | ||
|
|
fb8f5120e0 | ||
|
|
c9bcf947c6 | ||
|
|
7100612187 | ||
|
|
b1d1022930 | ||
|
|
1c39460172 | ||
|
|
ed12e59e67 | ||
|
|
30563b19ef | ||
|
|
79f1ee85c0 | ||
|
|
12d38bc8fc | ||
|
|
70b15f5f9a | ||
|
|
207744b628 | ||
|
|
f07e0868e5 | ||
|
|
38bf3d0d34 | ||
|
|
a0e5bd4769 | ||
|
|
601dec9768 | ||
|
|
63cb5ee909 | ||
|
|
e3d8bd0242 | ||
|
|
489e334acb | ||
|
|
8c9069b765 | ||
|
|
1066421df5 | ||
|
|
6535dc3e66 | ||
|
|
05d75eb9e2 | ||
|
|
7dc5aaa7a4 | ||
|
|
08a4c8f6ad | ||
|
|
f8fb029d95 | ||
|
|
053cce5f51 | ||
|
|
4afbe84391 | ||
|
|
abd87c42ca | ||
|
|
50876fee39 | ||
|
|
56ca97d74e | ||
|
|
32b90262ed | ||
|
|
e3db36613e | ||
|
|
b96299e3d0 | ||
|
|
9dc06419cf | ||
|
|
d9ffcdf59b | ||
|
|
4f4d7a19f1 | ||
|
|
b65ede4f4f | ||
|
|
ff344082c6 | ||
|
|
387684445e | ||
|
|
9ee9de7695 | ||
|
|
fdc7a04141 | ||
|
|
399a51b2bb | ||
|
|
5c146c0ba1 | ||
|
|
f11196975b | ||
|
|
728a2e7276 | ||
|
|
f3ac621bbf | ||
|
|
1e67e6f2af | ||
|
|
fc3e915da6 | ||
|
|
e8830d2837 | ||
|
|
ff45b12b13 | ||
|
|
77ea27f340 | ||
|
|
9086a07f69 | ||
|
|
69f06c2b12 | ||
|
|
5737093e66 | ||
|
|
b5ebec5167 | ||
|
|
56d519a780 | ||
|
|
0805130582 | ||
|
|
9ef6380f0a | ||
|
|
a669a7ee75 | ||
|
|
e89d2006f5 | ||
|
|
a17522095c | ||
|
|
61f4b7c1e5 | ||
|
|
104f434f57 | ||
|
|
e6d03ebc9a | ||
|
|
13b34a8c50 | ||
|
|
9b541ce614 | ||
|
|
391a7da7da | ||
|
|
fd152df645 | ||
|
|
1bfdfb1a24 | ||
|
|
0d93cbf797 | ||
|
|
aaab58e9b2 | ||
|
|
af48ab19d6 | ||
|
|
d5fd2710fc | ||
|
|
93becd5a98 | ||
|
|
4e6eb6c53a | ||
|
|
85ac31af36 | ||
|
|
594657acd0 | ||
|
|
a1bfb0da5b | ||
|
|
9742ffe769 | ||
|
|
a9ddb52c5d | ||
|
|
5babbe19c3 | ||
|
|
fd8bab6348 | ||
|
|
e6764c1bdf | ||
|
|
d998f87099 | ||
|
|
e90e035825 | ||
|
|
3817597229 | ||
|
|
d97da4d532 | ||
|
|
1e2b6fed14 | ||
|
|
31cd1cb5e8 | ||
|
|
d567e95f7f | ||
|
|
354530ba66 | ||
|
|
c532ecbfb8 | ||
|
|
6e5a887fdb | ||
|
|
2632b0ad09 | ||
|
|
8577330e27 | ||
|
|
996be526fb | ||
|
|
e3146abae1 | ||
|
|
7f756c5028 | ||
|
|
94e570917a | ||
|
|
5c11fb87c2 | ||
|
|
67a0e4bf28 | ||
|
|
c4485fe742 | ||
|
|
33f56831b7 | ||
|
|
cc467c1b74 | ||
|
|
ea3271b49e | ||
|
|
3eeddfdd85 | ||
|
|
7df7e7c9e9 | ||
|
|
c5a20a334e | ||
|
|
3c5e9459de | ||
|
|
77f99cec6f | ||
|
|
39d6384b15 | ||
|
|
1115558d0d | ||
|
|
d6d1226a6c | ||
|
|
7ecff3bd9c | ||
|
|
98bf800d78 | ||
|
|
bd897b67d3 | ||
|
|
a3b5c6b716 | ||
|
|
c67d6e8474 | ||
|
|
29d8800907 | ||
|
|
2a769dd43e | ||
|
|
cdfb6484b8 | ||
|
|
4f3eacd322 | ||
|
|
9690659278 | ||
|
|
da009b5130 | ||
|
|
1bebc5baee | ||
|
|
199405cb56 | ||
|
|
45fcde1d73 | ||
|
|
b12eca2460 | ||
|
|
092cd39ed7 | ||
|
|
b349d12326 | ||
|
|
fe375548a5 | ||
|
|
2a771ab203 | ||
|
|
d90e54849a | ||
|
|
f85e3ce24b | ||
|
|
61f667622a | ||
|
|
d60e2abcce | ||
|
|
ceec364360 | ||
|
|
fffdc70a5c | ||
|
|
b94136e99c | ||
|
|
7257f13b9b | ||
|
|
e90ad0afdc | ||
|
|
67e44a2d3c | ||
|
|
01c199b0d0 | ||
|
|
4e53ea3ee5 | ||
|
|
28a06a16eb | ||
|
|
8d5d74dc48 | ||
|
|
209e192942 | ||
|
|
515c15a662 | ||
|
|
54d90a1062 | ||
|
|
c5a6776ccc | ||
|
|
8cbc22bb29 | ||
|
|
2b17edc82d | ||
|
|
1f79572c07 | ||
|
|
d15ddb5923 | ||
|
|
25fed73b74 | ||
|
|
82f7908384 | ||
|
|
ec294cd951 | ||
|
|
2fba579edd | ||
|
|
efe671ceff | ||
|
|
169a014437 | ||
|
|
41a14d440f | ||
|
|
f120bf56b0 | ||
|
|
d5dc89004e | ||
|
|
a60d83f588 | ||
|
|
e332a9bd71 | ||
|
|
b8ec9e1935 | ||
|
|
2cea42184b | ||
|
|
981256287a | ||
|
|
c2b84a6de4 | ||
|
|
5fea7316bd | ||
|
|
f3ef9224ef | ||
|
|
92c785746e | ||
|
|
b10ba79056 | ||
|
|
d73f29941d | ||
|
|
b0fccf1d8f | ||
|
|
2c93f6038e | ||
|
|
588e2c71f1 | ||
|
|
8aaaed0f3c | ||
|
|
0df1041339 | ||
|
|
5470222496 | ||
|
|
b86d43d829 | ||
|
|
df96cb890b | ||
|
|
db89739e6d | ||
|
|
02134ceaf8 | ||
|
|
958caabd8e | ||
|
|
9406bcc2e5 | ||
|
|
b19dbc9ffd | ||
|
|
021dd04707 | ||
|
|
fc43cc703e | ||
|
|
a99e99f70f | ||
|
|
0051cba426 | ||
|
|
6aabb3d6df | ||
|
|
16cca6572c | ||
|
|
af11ca49fe | ||
|
|
0e07147d07 | ||
|
|
8e5573b8f9 | ||
|
|
e7fc1844a2 | ||
|
|
4759724d2b | ||
|
|
96086c1b6e | ||
|
|
fd63f74b98 | ||
|
|
d7e6a145e9 | ||
|
|
6a3b449e46 | ||
|
|
a2a9124f07 | ||
|
|
a18a959ef6 | ||
|
|
444b3c0af4 | ||
|
|
eae2fe427d | ||
|
|
970bf46d8c | ||
|
|
0d0ebeeacb | ||
|
|
c8a9e3e443 | ||
|
|
9bbd2fe078 | ||
|
|
25b2bb9e30 | ||
|
|
7dda099a50 | ||
|
|
9f9376e7bf | ||
|
|
4549f271a2 | ||
|
|
ca4ef952c8 | ||
|
|
92c2b2566b | ||
|
|
4a7d5938f1 | ||
|
|
e50eb147f4 | ||
|
|
e0eedae8a0 | ||
|
|
5ac49e58f6 | ||
|
|
3b65dd9765 | ||
|
|
d882c26c03 | ||
|
|
319d8bdde4 | ||
|
|
a8c065cfc8 | ||
|
|
f57b8d0eec | ||
|
|
bafc8ab28d | ||
|
|
48179125f4 | ||
|
|
6468c548e3 | ||
|
|
e165440623 | ||
|
|
2e1936df52 | ||
|
|
1a52d98966 | ||
|
|
05ce9531d1 | ||
|
|
20e400b101 | ||
|
|
123f907f83 | ||
|
|
dd91ece92a | ||
|
|
462f555d5f | ||
|
|
b05d419b2f | ||
|
|
e435b772f3 | ||
|
|
ce345a3c71 | ||
|
|
110e3f2e8b | ||
|
|
83a8ebff7e | ||
|
|
ff7141fa43 | ||
|
|
5f4cc07a98 | ||
|
|
d855c7d3d2 | ||
|
|
bd145f8c3a | ||
|
|
99a1e4a557 | ||
|
|
cbaa5c8228 | ||
|
|
cc767d3964 | ||
|
|
8320681e92 | ||
|
|
c01b333d77 | ||
|
|
bbdba2b7c5 | ||
|
|
db170b67ad | ||
|
|
dd8077d7e2 | ||
|
|
006ee37e0a | ||
|
|
d607fb053a | ||
|
|
1db607822b | ||
|
|
72c07c4cd4 | ||
|
|
51ede1c550 | ||
|
|
6275df77a3 | ||
|
|
0d5f00117d | ||
|
|
b6bc3687ae | ||
|
|
e18f13c315 | ||
|
|
f41d2da14b | ||
|
|
1f8ebb83f5 | ||
|
|
cf5af654e1 | ||
|
|
5afbad5616 | ||
|
|
0f4360fa63 | ||
|
|
39c9362a41 | ||
|
|
3e08481516 | ||
|
|
90f9278b69 | ||
|
|
6741e69b08 | ||
|
|
88b4a75f95 | ||
|
|
1c3831aa72 | ||
|
|
38d3be5354 | ||
|
|
d495c081cb | ||
|
|
3a5a014590 | ||
|
|
6f94bc4b1a | ||
|
|
11da788756 | ||
|
|
3a5c59d22d | ||
|
|
952f02ebc9 | ||
|
|
4c649ef750 | ||
|
|
2fe12c664f | ||
|
|
fc0a28cd20 | ||
|
|
7bf3d4c69f | ||
|
|
4b43a696be | ||
|
|
fc6f0b7da9 | ||
|
|
386a1769ba | ||
|
|
48415a4d87 | ||
|
|
52db213cea | ||
|
|
5a8f26fb5b | ||
|
|
84ec51da54 | ||
|
|
5d64fbd9af | ||
|
|
514c12db0c | ||
|
|
0bc593c3df | ||
|
|
2f243ab266 | ||
|
|
7a0fa222c4 | ||
|
|
88d036c636 | ||
|
|
3b510a6073 | ||
|
|
5cfd7cd69a | ||
|
|
d5a5a7fd17 | ||
|
|
b9989b36dc | ||
|
|
84f1f4969b | ||
|
|
1945dbdbc3 | ||
|
|
cc4a905685 | ||
|
|
7b6630512b | ||
|
|
63e0f14ad3 | ||
|
|
18054e9603 | ||
|
|
9a6c652da0 | ||
|
|
55423425d7 | ||
|
|
d436094e8c | ||
|
|
9184b038b3 | ||
|
|
aad020b9b9 | ||
|
|
64b6bbd45b | ||
|
|
58724320b6 | ||
|
|
20fbdc7130 | ||
|
|
93aed2580e | ||
|
|
5e8ceae3da | ||
|
|
2f26e555f9 | ||
|
|
48b3555e40 | ||
|
|
657852a82f | ||
|
|
dd812ca58c | ||
|
|
2c37075c22 | ||
|
|
c895de54bf | ||
|
|
3e9c2e0131 | ||
|
|
075099d217 | ||
|
|
91e614d6ea | ||
|
|
5167ebd7c4 | ||
|
|
b5ecc66ea2 | ||
|
|
f49ef8b999 | ||
|
|
6691082bb7 | ||
|
|
8956cd45c9 | ||
|
|
33178022ec | ||
|
|
e0f034c911 | ||
|
|
65183c8142 | ||
|
|
a1dce3c1e3 | ||
|
|
27381582f8 | ||
|
|
326e27f0cd | ||
|
|
f2fc6d2299 | ||
|
|
06af4a926a | ||
|
|
672236ba8f | ||
|
|
2f692a206d | ||
|
|
ac74479c3c | ||
|
|
88a1a56e9b | ||
|
|
12c4ff669a | ||
|
|
48576c8dfb | ||
|
|
6802e4a136 | ||
|
|
4be4b69d15 | ||
|
|
a10855cb4d | ||
|
|
01aa69185e | ||
|
|
aa1c50f7a7 | ||
|
|
a74e071847 | ||
|
|
67a084e597 | ||
|
|
c5b84d1fa0 | ||
|
|
d8468be21a | ||
|
|
c31b7598e4 | ||
|
|
fa3dc1add1 | ||
|
|
81a405c48c | ||
|
|
0dc54213fc | ||
|
|
7adeeaf607 | ||
|
|
c316f03b10 | ||
|
|
fa96e6dc3a | ||
|
|
bff57c695e | ||
|
|
73ad7a1923 | ||
|
|
4f0c23f6f1 | ||
|
|
e40f9ac769 | ||
|
|
11d0fe0191 | ||
|
|
ca60b9e579 | ||
|
|
f424ab3a1f | ||
|
|
a72357397e | ||
|
|
819bf7a84e | ||
|
|
b2b597542d | ||
|
|
c4608f9465 | ||
|
|
6828ee95d7 | ||
|
|
3cecde7c50 | ||
|
|
1aec2dbfb4 | ||
|
|
ba3f28cd5b | ||
|
|
b8b6a749ce | ||
|
|
1d1c64119d | ||
|
|
e93e4d03a1 | ||
|
|
1ddbb1b197 | ||
|
|
3632c3b19e | ||
|
|
25651d84dd | ||
|
|
5a59b245ce | ||
|
|
cf33f8bf74 | ||
|
|
bfb86a67da | ||
|
|
c076f7641d | ||
|
|
ff6efc7681 | ||
|
|
30a0583aab | ||
|
|
ea27a1802d | ||
|
|
9c23bbd309 | ||
|
|
a0680ffa8f | ||
|
|
94c4b723ad | ||
|
|
23ee6c2bb1 | ||
|
|
02058e523f | ||
|
|
e1951f3637 | ||
|
|
7039478ebc | ||
|
|
ff566466c8 | ||
|
|
3dae1aac2d | ||
|
|
43dad21cad | ||
|
|
9f07373e33 | ||
|
|
b09e4f3b6a | ||
|
|
be66132498 | ||
|
|
a6a70cc88e | ||
|
|
63d04b7734 | ||
|
|
90edd71274 | ||
|
|
db0252dc2c | ||
|
|
8b3e13ecba | ||
|
|
5ac96dd852 | ||
|
|
cf1ad22af1 | ||
|
|
4cf7e6888b | ||
|
|
1aa4e8bbb2 | ||
|
|
d9db327ffa | ||
|
|
6f484766ac | ||
|
|
9b6468c0b4 | ||
|
|
c5880c9096 | ||
|
|
4d588b62cb | ||
|
|
f6d2ab2e0e | ||
|
|
c52636a6e8 | ||
|
|
a24fb43ae8 | ||
|
|
8f7ead0687 | ||
|
|
39e6cc64a2 | ||
|
|
4f985776e1 | ||
|
|
b9e992f118 | ||
|
|
39e5f969e8 | ||
|
|
ee79ce4bf6 | ||
|
|
20e7a98395 | ||
|
|
c66be99be7 | ||
|
|
0bb5873fc5 | ||
|
|
50bf0b4a3b | ||
|
|
d664652b53 | ||
|
|
77d500235b | ||
|
|
a7811d9425 | ||
|
|
6c6d9d507f | ||
|
|
36ebc21d3e | ||
|
|
12f900cb6c | ||
|
|
e515bb4933 | ||
|
|
d93f46f4d6 | ||
|
|
1d4aaf04fd | ||
|
|
65469210b1 | ||
|
|
88a8bf2769 | ||
|
|
8429ff3150 | ||
|
|
890d352a65 | ||
|
|
acb85071f0 | ||
|
|
e41a60613c | ||
|
|
9001668e1b | ||
|
|
7b78f22fcc | ||
|
|
b614e6c1a4 | ||
|
|
187abcbcdf | ||
|
|
5a3a755f1a | ||
|
|
386e539148 | ||
|
|
d05375447b | ||
|
|
0fc5791b8e | ||
|
|
0e4f851098 | ||
|
|
2488378099 | ||
|
|
b906890de1 | ||
|
|
feb0236d50 | ||
|
|
22104a9bdb | ||
|
|
d0ccd9d77a | ||
|
|
dc6a7cf712 | ||
|
|
795d6bdab6 | ||
|
|
a2b41531a0 | ||
|
|
6ed4301ba4 | ||
|
|
7abab63049 | ||
|
|
b29fdd841b | ||
|
|
7e73f6f074 | ||
|
|
efc1efdfe1 | ||
|
|
11fdff952c | ||
|
|
14f90b66f2 | ||
|
|
a8d1676156 | ||
|
|
951f588a31 | ||
|
|
7081627776 | ||
|
|
391576f080 | ||
|
|
8cca3b9ef6 | ||
|
|
47c5f14eda | ||
|
|
a757b3b326 | ||
|
|
1e1475c0e9 | ||
|
|
fa68a17ea3 | ||
|
|
dc1bb0e2c1 | ||
|
|
656cfb62ff | ||
|
|
65b26a25ea | ||
|
|
6a03246234 | ||
|
|
53289b8616 | ||
|
|
349eb433ce | ||
|
|
9a98e0db24 | ||
|
|
b89e8baba0 | ||
|
|
773f276a78 | ||
|
|
1085923163 | ||
|
|
6b3ffed3e4 | ||
|
|
16a142c3c4 | ||
|
|
2b660c4d45 | ||
|
|
6283987323 | ||
|
|
fd778b0fa8 | ||
|
|
8f03d92f5b | ||
|
|
2ca624e9e2 | ||
|
|
514b00f7af | ||
|
|
05b7f6dbe9 | ||
|
|
d22eb9c85a | ||
|
|
4bd60c04a5 | ||
|
|
f361e61ce9 | ||
|
|
1e5807c585 | ||
|
|
8239b130bf | ||
|
|
09acf97c8d | ||
|
|
6e72d0bb14 | ||
|
|
34c6659703 | ||
|
|
42a067a32a | ||
|
|
f2a995ccdc | ||
|
|
463f064919 | ||
|
|
bec20e7e5d | ||
|
|
da18b35d68 | ||
|
|
842d7f453c | ||
|
|
74e63fd176 | ||
|
|
c8ec229629 | ||
|
|
d955e09268 | ||
|
|
106dfd8d47 | ||
|
|
aa4ff53d62 | ||
|
|
2a9e9932f6 | ||
|
|
df853d9867 | ||
|
|
bcd185e508 | ||
|
|
2032c30a4d | ||
|
|
2b8e217459 | ||
|
|
29948c246d | ||
|
|
901d0effe7 | ||
|
|
6a21f98d14 | ||
|
|
6eb05ce9b4 | ||
|
|
cae3414ddb | ||
|
|
3e067c9ea5 | ||
|
|
12316e8611 | ||
|
|
bf3370fad1 | ||
|
|
2cb2868d47 | ||
|
|
6ab33ba06c | ||
|
|
f826575567 | ||
|
|
498879a235 | ||
|
|
0283c5204f | ||
|
|
5bb7fea3ca | ||
|
|
593f0e7a18 | ||
|
|
1158c43430 | ||
|
|
041d53c434 | ||
|
|
1e60b41226 | ||
|
|
855d831c33 | ||
|
|
425efa412f | ||
|
|
0b5a284ceb | ||
|
|
75f1e6e569 | ||
|
|
0258316d21 | ||
|
|
b55cd42aaf | ||
|
|
8781a53f21 | ||
|
|
75a2b47abf | ||
|
|
9b531f83a6 | ||
|
|
c7c3b01805 | ||
|
|
cd5f5216bb | ||
|
|
8f87539026 | ||
|
|
c63c4c349e | ||
|
|
10f3923376 | ||
|
|
384a18fd65 | ||
|
|
c0c890302b | ||
|
|
8a3d3f5783 | ||
|
|
f322610661 | ||
|
|
a87acd6dc2 | ||
|
|
ebe7d44386 | ||
|
|
e55c25dc94 | ||
|
|
3f34745a15 | ||
|
|
f4b32ca436 | ||
|
|
8b156a87bd | ||
|
|
f6142e576b | ||
|
|
5d5905249c | ||
|
|
b9396534e5 | ||
|
|
cff40a31e5 | ||
|
|
aa908f7a61 | ||
|
|
429d62991a | ||
|
|
14bcb6ac2b | ||
|
|
5067175174 | ||
|
|
7879f17dac | ||
|
|
3be1cf2074 | ||
|
|
424f5b4794 | ||
|
|
b64583510c | ||
|
|
2e114b0cfb | ||
|
|
f56c76cf15 | ||
|
|
8b0f7148e7 | ||
|
|
c600c30eaa | ||
|
|
b2efd544dc | ||
|
|
e3a709d261 | ||
|
|
3028d6a7af | ||
|
|
0adf9df0b5 | ||
|
|
4e25774931 | ||
|
|
e8808e8d7d | ||
|
|
f4a53cfc05 | ||
|
|
0f6ff9c3a0 | ||
|
|
6ac4082bcd | ||
|
|
4d87b338e5 | ||
|
|
88ee16965b | ||
|
|
408fd4ddfa | ||
|
|
5068a3cfc1 | ||
|
|
376bc20472 | ||
|
|
dc3606b53a | ||
|
|
49cc5c060f | ||
|
|
dbe3ee555d | ||
|
|
b273c95494 | ||
|
|
a46519c964 | ||
|
|
7f9cbe6d46 | ||
|
|
b94dcabbd5 | ||
|
|
e8b2c7b470 | ||
|
|
899e5ed7ed | ||
|
|
04cf4eaa76 | ||
|
|
9ca336c47f | ||
|
|
dac818db4d | ||
|
|
21a8ea11a3 | ||
|
|
52af7c44f1 | ||
|
|
18b9bd8e4b | ||
|
|
5cdf7573ee | ||
|
|
3c415591db | ||
|
|
667fdc0163 | ||
|
|
10569b1426 | ||
|
|
2f4ddeab9f | ||
|
|
235ce4873f | ||
|
|
b26e1e12d6 | ||
|
|
ef1a2fe75e | ||
|
|
c7766c05d2 | ||
|
|
85c8b636a8 | ||
|
|
43b80f24e6 | ||
|
|
c7e6fd6a1b | ||
|
|
7ca4ad60c1 | ||
|
|
a81a31ac66 | ||
|
|
6b3eda7c4a | ||
|
|
68243ee844 | ||
|
|
6196daeead | ||
|
|
81c420c2e3 | ||
|
|
c533da896c | ||
|
|
29f5f33a12 | ||
|
|
aa7734d72b | ||
|
|
e5a2132dfd | ||
|
|
f766594ef3 | ||
|
|
78383bf9d7 | ||
|
|
45c0183f97 | ||
|
|
ce52864fbc | ||
|
|
5dae482265 | ||
|
|
cef73ca693 | ||
|
|
0ffe3037d5 | ||
|
|
af164039fa | ||
|
|
2cf30dcb2c | ||
|
|
4a99ccabd9 | ||
|
|
9c0d0d0fac | ||
|
|
f6a33bde65 | ||
|
|
3ac1d203a9 | ||
|
|
e9d78688d7 | ||
|
|
69a73cc25e | ||
|
|
aaf01f4a0a | ||
|
|
30e6c70346 | ||
|
|
7c01d81483 | ||
|
|
4ace644304 | ||
|
|
7b66e7eb41 | ||
|
|
8e7667b9e5 | ||
|
|
a92b5c5658 | ||
|
|
1013ba7b17 | ||
|
|
8ae64febb4 | ||
|
|
2ac6b2a3cb | ||
|
|
04a748094a | ||
|
|
1f0e20ea25 | ||
|
|
ce2a05c4cf | ||
|
|
a5293d714b | ||
|
|
62a46cb595 | ||
|
|
1471b26c7a | ||
|
|
3a79b36a85 | ||
|
|
5ca8ad7266 | ||
|
|
3e75368514 | ||
|
|
0d8d1e091f | ||
|
|
1bc7b5bcef | ||
|
|
668617340d | ||
|
|
bf49c8275d | ||
|
|
93412e9d63 | ||
|
|
600c6b6255 | ||
|
|
5d498442f1 | ||
|
|
be243c7a28 | ||
|
|
57593b27dd | ||
|
|
ca8344d9e2 | ||
|
|
d305ee6cb2 | ||
|
|
67ff2538e8 | ||
|
|
0438786ca6 | ||
|
|
5e4bb85df0 | ||
|
|
f58de95db7 | ||
|
|
aee55c8bc9 | ||
|
|
128cbb9d5b | ||
|
|
688bc17c6b | ||
|
|
dfdffb17cb | ||
|
|
1f2be59c91 | ||
|
|
2abb11b62e | ||
|
|
e0674a2817 | ||
|
|
0a45e7ef5b | ||
|
|
93dbef1106 | ||
|
|
35a1fbd154 | ||
|
|
1c0981ac3a | ||
|
|
00669c15fb | ||
|
|
505915232c | ||
|
|
ce7d5a40e9 | ||
|
|
8de28b6294 | ||
|
|
cb9f7cbd57 | ||
|
|
b67655002c | ||
|
|
b87e59159f | ||
|
|
f64921629b | ||
|
|
107bd1ec17 | ||
|
|
1a8e36ea11 | ||
|
|
5b600f6c06 | ||
|
|
925c5aa088 | ||
|
|
25923d9d8c | ||
|
|
0effe70b6e | ||
|
|
a1d39bc6b4 | ||
|
|
72a6fbb97f | ||
|
|
9515bef2fa | ||
|
|
f48cb80acc | ||
|
|
32b1a834c8 | ||
|
|
4fcb4b6537 | ||
|
|
9ccd250b6b | ||
|
|
82b258a014 | ||
|
|
d3307b955b | ||
|
|
3b1cf3264d | ||
|
|
dc58ad97fa | ||
|
|
2ec1640d99 | ||
|
|
31ac8367f4 | ||
|
|
3ab73165fe | ||
|
|
512f5d56a2 | ||
|
|
dbea3aba6e | ||
|
|
448d5e3e11 | ||
|
|
51440ece93 | ||
|
|
fbd5be914e | ||
|
|
8df6d654d1 | ||
|
|
dba407dcac | ||
|
|
eec4d5c44d | ||
|
|
254f256299 | ||
|
|
ed309a1270 | ||
|
|
3bfe531a79 | ||
|
|
2d0f5ffee3 | ||
|
|
7ef3a508fd | ||
|
|
412a33349d | ||
|
|
984327180f | ||
|
|
86aeb17e06 | ||
|
|
938e93afa4 | ||
|
|
55b539a3e3 | ||
|
|
d23f763fa5 | ||
|
|
c2ebdbeaec | ||
|
|
443e980b86 | ||
|
|
5ff9cbe2ac | ||
|
|
c1a3428e1b | ||
|
|
41286e5684 | ||
|
|
966dbc2b23 | ||
|
|
ba6a251644 | ||
|
|
694d8c3b2f | ||
|
|
9308eed9ec | ||
|
|
9377111807 | ||
|
|
7987e5c098 | ||
|
|
01410b02b1 | ||
|
|
6d2a115358 | ||
|
|
b85f386307 | ||
|
|
6c40adfb5f | ||
|
|
e5d92c99c5 | ||
|
|
339a41a9b6 | ||
|
|
c66417b4ea | ||
|
|
03109d6e45 | ||
|
|
efc5f9781d | ||
|
|
fcec0882c7 | ||
|
|
7a16dc50f3 | ||
|
|
cc9e31f018 | ||
|
|
3b97d6bae7 | ||
|
|
6ccae67e58 | ||
|
|
1ab2210bbe | ||
|
|
88f68c24bd | ||
|
|
37d3a7d47f | ||
|
|
74889b2a00 | ||
|
|
815c868088 | ||
|
|
acb5bc8951 | ||
|
|
ce83def12a | ||
|
|
7bb326e3cd | ||
|
|
7f6f43fbe6 | ||
|
|
7b00b49cb8 | ||
|
|
0759c58eb2 | ||
|
|
b97c67d786 | ||
|
|
5c689edb0e | ||
|
|
a166a9ec07 | ||
|
|
8d8cc4c625 | ||
|
|
bb1c530c28 | ||
|
|
db50442174 | ||
|
|
f403bc788e | ||
|
|
ed1f9a9c45 | ||
|
|
aee48bd53f | ||
|
|
d3a31a5b85 | ||
|
|
088f457bef | ||
|
|
fc15be9b72 | ||
|
|
77a77fab9a | ||
|
|
b45e7dbd5c | ||
|
|
cd93287d70 | ||
|
|
41d3a3d854 | ||
|
|
94bc38d12e | ||
|
|
c86510df02 | ||
|
|
173bf45bec | ||
|
|
8b4d1f351a | ||
|
|
7019685f3a | ||
|
|
9856ba0dec | ||
|
|
b6904a6f01 |
244
.editorconfig
Normal file
244
.editorconfig
Normal file
@@ -0,0 +1,244 @@
|
||||
# Remove the line below if you want to inherit .editorconfig settings from higher directories
|
||||
root = true
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
|
||||
#### Core EditorConfig Options ####
|
||||
|
||||
# Indentation and spacing
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
tab_width = 4
|
||||
|
||||
# New line preferences
|
||||
end_of_line = crlf
|
||||
insert_final_newline = false
|
||||
|
||||
#### .NET Code Actions ####
|
||||
|
||||
# Type members
|
||||
dotnet_hide_advanced_members = false
|
||||
dotnet_member_insertion_location = with_other_members_of_the_same_kind
|
||||
dotnet_property_generation_behavior = prefer_throwing_properties
|
||||
|
||||
# Symbol search
|
||||
dotnet_search_reference_assemblies = true
|
||||
|
||||
#### .NET Coding Conventions ####
|
||||
|
||||
# Organize usings
|
||||
dotnet_separate_import_directive_groups = false
|
||||
dotnet_sort_system_directives_first = false
|
||||
file_header_template = unset
|
||||
|
||||
# this. and Me. preferences
|
||||
dotnet_style_qualification_for_event = false
|
||||
dotnet_style_qualification_for_field = false
|
||||
dotnet_style_qualification_for_method = false
|
||||
dotnet_style_qualification_for_property = false
|
||||
|
||||
# Language keywords vs BCL types preferences
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true
|
||||
dotnet_style_predefined_type_for_member_access = true
|
||||
|
||||
# Parentheses preferences
|
||||
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
|
||||
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
|
||||
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
|
||||
|
||||
# Modifier preferences
|
||||
dotnet_style_require_accessibility_modifiers = for_non_interface_members
|
||||
|
||||
# Expression-level preferences
|
||||
dotnet_prefer_system_hash_code = true
|
||||
dotnet_style_coalesce_expression = true
|
||||
dotnet_style_collection_initializer = true
|
||||
dotnet_style_explicit_tuple_names = true
|
||||
dotnet_style_namespace_match_folder = true
|
||||
dotnet_style_null_propagation = true
|
||||
dotnet_style_object_initializer = true
|
||||
dotnet_style_operator_placement_when_wrapping = beginning_of_line
|
||||
dotnet_style_prefer_auto_properties = true
|
||||
dotnet_style_prefer_collection_expression = when_types_loosely_match
|
||||
dotnet_style_prefer_compound_assignment = true
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true
|
||||
dotnet_style_prefer_conditional_expression_over_return = true
|
||||
dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true
|
||||
dotnet_style_prefer_inferred_tuple_names = true
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true
|
||||
dotnet_style_prefer_simplified_boolean_expressions = true
|
||||
dotnet_style_prefer_simplified_interpolation = true
|
||||
|
||||
# Field preferences
|
||||
dotnet_style_readonly_field = true
|
||||
|
||||
# Parameter preferences
|
||||
dotnet_code_quality_unused_parameters = all
|
||||
|
||||
# Suppression preferences
|
||||
dotnet_remove_unnecessary_suppression_exclusions = none
|
||||
|
||||
# New line preferences
|
||||
dotnet_style_allow_multiple_blank_lines_experimental = true
|
||||
dotnet_style_allow_statement_immediately_after_block_experimental = true
|
||||
|
||||
#### C# Coding Conventions ####
|
||||
|
||||
# var preferences
|
||||
csharp_style_var_elsewhere = false
|
||||
csharp_style_var_for_built_in_types = false
|
||||
csharp_style_var_when_type_is_apparent = false
|
||||
|
||||
# Expression-bodied members
|
||||
csharp_style_expression_bodied_accessors = true
|
||||
csharp_style_expression_bodied_constructors = false
|
||||
csharp_style_expression_bodied_indexers = true
|
||||
csharp_style_expression_bodied_lambdas = true
|
||||
csharp_style_expression_bodied_local_functions = false
|
||||
csharp_style_expression_bodied_methods = false
|
||||
csharp_style_expression_bodied_operators = false
|
||||
csharp_style_expression_bodied_properties = true
|
||||
|
||||
# Pattern matching preferences
|
||||
csharp_style_pattern_matching_over_as_with_null_check = true
|
||||
csharp_style_pattern_matching_over_is_with_cast_check = true
|
||||
csharp_style_prefer_extended_property_pattern = true
|
||||
csharp_style_prefer_not_pattern = true
|
||||
csharp_style_prefer_pattern_matching = true
|
||||
csharp_style_prefer_switch_expression = true
|
||||
|
||||
# Null-checking preferences
|
||||
csharp_style_conditional_delegate_call = true
|
||||
|
||||
# Modifier preferences
|
||||
csharp_prefer_static_anonymous_function = true
|
||||
csharp_prefer_static_local_function = true
|
||||
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
|
||||
csharp_style_prefer_readonly_struct = true
|
||||
csharp_style_prefer_readonly_struct_member = true
|
||||
|
||||
# Code-block preferences
|
||||
csharp_prefer_braces = true
|
||||
csharp_prefer_simple_using_statement = true
|
||||
csharp_prefer_system_threading_lock = true
|
||||
csharp_style_namespace_declarations = block_scoped
|
||||
csharp_style_prefer_method_group_conversion = true
|
||||
csharp_style_prefer_primary_constructors = true
|
||||
csharp_style_prefer_top_level_statements = true
|
||||
|
||||
# Expression-level preferences
|
||||
csharp_prefer_simple_default_expression = true
|
||||
csharp_style_deconstructed_variable_declaration = true
|
||||
csharp_style_implicit_object_creation_when_type_is_apparent = true
|
||||
csharp_style_inlined_variable_declaration = true
|
||||
csharp_style_prefer_index_operator = true
|
||||
csharp_style_prefer_local_over_anonymous_function = true
|
||||
csharp_style_prefer_null_check_over_type_check = true
|
||||
csharp_style_prefer_range_operator = true
|
||||
csharp_style_prefer_tuple_swap = true
|
||||
csharp_style_prefer_utf8_string_literals = true
|
||||
csharp_style_throw_expression = true
|
||||
csharp_style_unused_value_assignment_preference = discard_variable
|
||||
csharp_style_unused_value_expression_statement_preference = discard_variable
|
||||
|
||||
# 'using' directive preferences
|
||||
csharp_using_directive_placement = outside_namespace
|
||||
|
||||
# New line preferences
|
||||
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
|
||||
csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
|
||||
csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
|
||||
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
|
||||
csharp_style_allow_embedded_statements_on_same_line_experimental = true
|
||||
|
||||
#### C# Formatting Rules ####
|
||||
|
||||
# New line preferences
|
||||
csharp_new_line_before_catch = true
|
||||
csharp_new_line_before_else = true
|
||||
csharp_new_line_before_finally = true
|
||||
csharp_new_line_before_members_in_anonymous_types = true
|
||||
csharp_new_line_before_members_in_object_initializers = true
|
||||
csharp_new_line_before_open_brace = all
|
||||
csharp_new_line_between_query_expression_clauses = true
|
||||
|
||||
# Indentation preferences
|
||||
csharp_indent_block_contents = true
|
||||
csharp_indent_braces = false
|
||||
csharp_indent_case_contents = true
|
||||
csharp_indent_case_contents_when_block = true
|
||||
csharp_indent_labels = no_change
|
||||
csharp_indent_switch_labels = true
|
||||
|
||||
# Space preferences
|
||||
csharp_space_after_cast = false
|
||||
csharp_space_after_colon_in_inheritance_clause = true
|
||||
csharp_space_after_comma = true
|
||||
csharp_space_after_dot = false
|
||||
csharp_space_after_keywords_in_control_flow_statements = true
|
||||
csharp_space_after_semicolon_in_for_statement = true
|
||||
csharp_space_around_binary_operators = before_and_after
|
||||
csharp_space_around_declaration_statements = false
|
||||
csharp_space_before_colon_in_inheritance_clause = true
|
||||
csharp_space_before_comma = false
|
||||
csharp_space_before_dot = false
|
||||
csharp_space_before_open_square_brackets = false
|
||||
csharp_space_before_semicolon_in_for_statement = false
|
||||
csharp_space_between_empty_square_brackets = false
|
||||
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||
csharp_space_between_parentheses = false
|
||||
csharp_space_between_square_brackets = false
|
||||
|
||||
# Wrapping preferences
|
||||
csharp_preserve_single_line_blocks = true
|
||||
csharp_preserve_single_line_statements = true
|
||||
|
||||
#### Naming styles ####
|
||||
|
||||
# Naming rules
|
||||
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
|
||||
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
|
||||
|
||||
dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
|
||||
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
|
||||
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
|
||||
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
|
||||
|
||||
# Symbol specifications
|
||||
|
||||
dotnet_naming_symbols.interface.applicable_kinds = interface
|
||||
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.interface.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
|
||||
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.types.required_modifiers =
|
||||
|
||||
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
|
||||
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
|
||||
dotnet_naming_symbols.non_field_members.required_modifiers =
|
||||
|
||||
# Naming styles
|
||||
|
||||
dotnet_naming_style.pascal_case.required_prefix =
|
||||
dotnet_naming_style.pascal_case.required_suffix =
|
||||
dotnet_naming_style.pascal_case.word_separator =
|
||||
dotnet_naming_style.pascal_case.capitalization = pascal_case
|
||||
|
||||
dotnet_naming_style.begins_with_i.required_prefix = I
|
||||
dotnet_naming_style.begins_with_i.required_suffix =
|
||||
dotnet_naming_style.begins_with_i.word_separator =
|
||||
dotnet_naming_style.begins_with_i.capitalization = pascal_case
|
||||
11
.github/ISSUE_TEMPLATE/bug_report.md
vendored
11
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -11,10 +11,10 @@ assignees: ''
|
||||
|
||||
IMPORTANT: Read this first!!!
|
||||
|
||||
1. If you own a Radzen Professional or Еnterprise subscription you can report your issue or ask us a question via email at info@radzen.com. Radzen staff will reply within 24 hours (Professional) or 16 hours (Enterprise)
|
||||
1. If you own a Radzen Blazor Pro or Team subscription you can also report your issue or ask us a question via email at info@radzen.com. Radzen staff will reply within 24 hours (Pro) or 16 hours (Team)
|
||||
2. The Radzen staff guarantees a response to issues in this repo only to paid subscribers.
|
||||
3. If you have a HOW TO question start a new forum thread in the Radzen Community forum: https://forum.radzen.com. Radzen staff will close issues that are HOWTO questions.
|
||||
4. Please adhere to the issue template. Specify all the steps required to reproduce the issue or link a project which reproduces it easily (without requiring extra steps such as restoring a database).
|
||||
4. Please adhere to the issue template. Specify all the steps required to reproduce the issue.
|
||||
-->
|
||||
|
||||
**Describe the bug**
|
||||
@@ -27,7 +27,12 @@ Steps to reproduce the behavior:
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
Alternatively link your repo with a sample project that can be run.
|
||||
Alternatively make a new [playground](https://blazor.radzen.com/playground) snippet and paste its URL.
|
||||
1. Go to any live demo at https://blazor.radzen.com
|
||||
2. Click the **Edit Source** tab.
|
||||
3. Then click **Open in Playground**.
|
||||
4. Reproduce the problem and save the snippet.
|
||||
5. Copy the snippet URL and provide it in the issue description.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -5,4 +5,4 @@ contact_links:
|
||||
about: Please ask and answer questions here.
|
||||
- name: Radzen Commercial Support
|
||||
url: info@radzen.com
|
||||
about: Radzen Professional or Enterprise subscribers can get dedicated support over email.
|
||||
about: Radzen Blazor subscribers can get dedicated support over email.
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -11,7 +11,7 @@ assignees: ''
|
||||
|
||||
IMPORTANT: Read this first!!!
|
||||
|
||||
1. If you own a Radzen Professional or Еnterprise subscription you can request your feature via email at info@radzen.com. Radzen staff will reply within 24 hours (Professional) or 16 hours (Enterprise)
|
||||
1. If you own a Radzen Blazor subscription you can request your feature via email at info@radzen.com. Radzen staff will reply within 24 hours (Pro) or 16 hours (Team)
|
||||
2. The Radzen staff guarantees a response to issues in this repo only to paid subscribers.
|
||||
3. If you have a HOW TO question start a new forum thread in the Radzen Community forum: https://forum.radzen.com. Radzen staff will close issues that are HOWTO questions.
|
||||
4. Please adhere to the issue template.
|
||||
|
||||
28
.github/workflows/ci.yml
vendored
Normal file
28
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
# This workflow will build a .NET project
|
||||
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
|
||||
|
||||
name: .NET
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build Radzen.Blazor/Radzen.Blazor.csproj
|
||||
- name: Test
|
||||
run: dotnet test Radzen.Blazor.Tests/Radzen.Blazor.Tests.csproj
|
||||
66
.github/workflows/deploy.yml
vendored
Normal file
66
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
name: Deploy to blazor.radzen.com
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: blazor-radzen-prod
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Compute image tag (timestamp)
|
||||
id: meta
|
||||
run: |
|
||||
TAG=$(date -u +"%Y%m%d%H%M%S")
|
||||
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${TAG}"
|
||||
echo "image=$IMAGE" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.image }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
- name: Push to dokku
|
||||
uses: dokku/github-action@master
|
||||
with:
|
||||
git_remote_url: ${{ secrets.DOKKU_REPO }}
|
||||
ssh_private_key: ${{ secrets.DOKKU_SSH_PRIVATE_KEY }}
|
||||
deploy_docker_image: ${{ steps.meta.outputs.image }}
|
||||
|
||||
- name: Prune GHCR versions (keep 1)
|
||||
uses: actions/delete-package-versions@v5
|
||||
with:
|
||||
package-name: radzen-blazor
|
||||
package-type: container
|
||||
min-versions-to-keep: 1
|
||||
delete-only-pre-release-versions: false
|
||||
17
.gitignore
vendored
17
.gitignore
vendored
@@ -8,6 +8,7 @@
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
global.json
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
@@ -330,4 +331,20 @@ ASALocalRun/
|
||||
.DS_Store
|
||||
.vscode
|
||||
issues.json
|
||||
|
||||
Radzen.Blazor/wwwroot/css/
|
||||
project.csproj
|
||||
RadzenBlazorDemos/wwwroot/docs/
|
||||
Radzen.DocFX/obj/
|
||||
Radzen.DocFX/_site/
|
||||
Radzen.DocFX/_exported_templates
|
||||
Radzen.DocFX/api/*.yml
|
||||
!Radzen.DocFX/api/index.md
|
||||
Radzen.DocFX/api/.manifest
|
||||
Radzen.Blazor.min.js
|
||||
/.claude
|
||||
/SANKEY_PATTERN_COMPARISON.md
|
||||
*.md
|
||||
/.gitignore
|
||||
/.gitignore
|
||||
RadzenBlazorDemos/wwwroot/demos
|
||||
|
||||
75
CONTRIBUTING.md
Normal file
75
CONTRIBUTING.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Contributing to Radzen.Blazor
|
||||
|
||||
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
|
||||
|
||||
This is a set of guidelines for contributing to Radzen.Blazor.
|
||||
|
||||
## Asking questions
|
||||
Please don't open an issue to ask a question about using Radzen.Blazor components. You can check the following resources instead:
|
||||
|
||||
### [Online demos](https://blazor.radzen.com)
|
||||
A showcase application that demonstrates all Radzen.Blazor components. You will find various use cases that demonstrate the component features and API. The source
|
||||
of the demos is available [here](https://github.com/radzenhq/radzen-blazor/tree/master/RadzenBlazorDemos).
|
||||
|
||||
### [Documentation](https://blazor.radzen.com/docs/)
|
||||
Technical documentation and API reference.
|
||||
|
||||
### [Community forum](https://forum.radzen.com)
|
||||
You can ask your question here. Please use the [Radzen.Blazor Components](https://forum.radzen.com/c/blazor-components/10) category.
|
||||
|
||||
### Dedicated technical support
|
||||
|
||||
Radzen staff provides technical support with guaranteed response time to Radzen Professional and Enterprise subscribers. The pricing options are available [here](https://www.radzen.com/pricing).
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting bugs
|
||||
|
||||
We are tracking bugs as [issues](https://github.com/radzenhq/radzen-blazor/issues).
|
||||
|
||||
Before creating bug reports, please check the existing issues as you might find out that you don't need to create one. When you are creating a bug report, please include as many details as possible.
|
||||
Fill out [the required template](https://github.com/radzenhq/radzen-blazor/blob/master/.github/ISSUE_TEMPLATE/bug_report.md), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
|
||||
|
||||
#### How Do I Submit A (Good) Bug Report?
|
||||
|
||||
After you've determined your bug hasn't been reported yet, create an issue in this repository and provide the following information by filling in [the template](https://github.com/radzenhq/radzen-blazor/blob/master/.github/ISSUE_TEMPLATE/bug_report.md).
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the problem.
|
||||
* **Describe the exact steps which reproduce the problem** in as many details as possible.
|
||||
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
|
||||
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
|
||||
* **Explain which behavior you expected to see instead and why.**
|
||||
* **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. You can use [this tool](https://www.cockos.com/licecap/) to record GIFs on macOS and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion, including completely new features and minor improvements to existing functionality.
|
||||
Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:.
|
||||
|
||||
After you've determined your feature hasn't been requested yet, create an issue in this repository and provide the following information by filling in [the template](https://github.com/radzenhq/radzen-blazor/blob/master/.github/ISSUE_TEMPLATE/feature_request.md).
|
||||
|
||||
Explain the enhancement and include additional details:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the suggestion.
|
||||
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
|
||||
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
|
||||
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
|
||||
* **Explain why this enhancement would be useful** to most Radzen.Blazor users.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
If you want to contribute a new feature of fix a bug you can open a pull request.
|
||||
|
||||
Make sure you follow this procedure:
|
||||
* **Important!!!** if you itent to make a lot of changes in a pull request open an issue to discuss this with us first. The Radzen Blazor Components have a lot of
|
||||
moving parts and making big changes should be done with extra precautions.
|
||||
* **Be sure that none of the existing tests** breaks after your changes. The test project is available [here](https://github.com/radzenhq/radzen-blazor/tree/master/Radzen.Blazor.Tests).
|
||||
* **If possible add new tests that verify your fix or new feature**.
|
||||
* **Follow the existing coding style** (to be described in detail later).
|
||||
|
||||
|
||||
|
||||
48
Dockerfile
Normal file
48
Dockerfile
Normal file
@@ -0,0 +1,48 @@
|
||||
# =============================
|
||||
# BUILD STAGE
|
||||
# =============================
|
||||
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||
WORKDIR /src
|
||||
|
||||
# Copy project files first for better caching
|
||||
COPY Radzen.Blazor/*.csproj Radzen.Blazor/
|
||||
COPY RadzenBlazorDemos/*.csproj RadzenBlazorDemos/
|
||||
COPY RadzenBlazorDemos.Host/*.csproj RadzenBlazorDemos.Host/
|
||||
|
||||
# Radzen.DocFX usually has no csproj → copy full folder
|
||||
COPY Radzen.DocFX/ Radzen.DocFX/
|
||||
|
||||
# Restore dependencies
|
||||
RUN dotnet restore RadzenBlazorDemos.Host/RadzenBlazorDemos.Host.csproj
|
||||
|
||||
# Copy full source after restore layer
|
||||
COPY . .
|
||||
|
||||
# Install docfx (build stage only)
|
||||
RUN dotnet tool install -g docfx
|
||||
ENV PATH="$PATH:/root/.dotnet/tools"
|
||||
|
||||
# Build shared project (keep net8.0 if required)
|
||||
RUN dotnet build -c Release Radzen.Blazor/Radzen.Blazor.csproj -f net8.0
|
||||
|
||||
# Generate documentation
|
||||
RUN docfx Radzen.DocFX/docfx.json
|
||||
|
||||
# Publish the Blazor host app
|
||||
WORKDIR /src/RadzenBlazorDemos.Host
|
||||
RUN dotnet publish -c Release -o /app/out
|
||||
|
||||
|
||||
# =============================
|
||||
# RUNTIME STAGE
|
||||
# =============================
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
||||
WORKDIR /app
|
||||
|
||||
# Copy only published output
|
||||
COPY --from=build /app/out ./
|
||||
|
||||
# Set runtime URL
|
||||
ENV ASPNETCORE_URLS=http://+:5000
|
||||
|
||||
ENTRYPOINT ["dotnet", "RadzenBlazorDemos.Host.dll"]
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2018-2021 Radzen Ltd
|
||||
Copyright (c) 2018-2025 Radzen Ltd
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
95
README.md
95
README.md
@@ -1,64 +1,57 @@
|
||||
# Radzen Blazor Components
|
||||

|
||||
|
||||
The home of the [Radzen Blazor components](https://blazor.radzen.com)
|
||||
Radzen Blazor Components
|
||||
========================
|
||||
|
||||
## Commercial support
|
||||
The most sophisticated free UI component library for Blazor, featuring **100+ native components**.
|
||||
|
||||
Paid support for the Radzen Blazor Components is available as part of the [Radzen Professional subscription](https://www.radzen.com/pricing/).
|
||||
See Online Demos or Read the Docs
|
||||
|
||||
Our flagship product Radzen provides tons of productivity features for Blazor developers:
|
||||
- The first in the industry WYSIWYG Blazor design time canvas
|
||||
[](https://github.com/radzenhq/radzen-blazor/blob/master/LICENSE)[ ](https://www.nuget.org/packages/Radzen.Blazor) [ ](https://github.com/radzenhq/radzen-blazor/graphs/contributors)[ ](https://blazor.radzen.com)[](https://blazor.radzen.com/docs)
|
||||
|
||||
## Why choose Radzen Blazor Components?
|
||||
|
||||
### :sparkles: Free
|
||||
|
||||
Radzen Blazor Components are open source and free for commercial use. You can install them from [NuGet](https://www.nuget.org/packages/Radzen.Blazor) or build your own copy from source.
|
||||
|
||||
Paid support is available as part of the [Radzen Blazor subscription](https://www.radzen.com/pricing).
|
||||
|
||||
### :computer: Native
|
||||
|
||||
The components are implemented in C# and take full advantage of the Blazor framework. They do not depend on or wrap existing JavaScript frameworks or libraries.
|
||||
|
||||
Blazor Server and Blazor WebAssembly are fully supported.
|
||||
|
||||
### :seedling: Growing
|
||||
|
||||
We add new components and features on a regular basis.
|
||||
|
||||
Short development cycle. We release as soon as new stuff is available. No more quarterly releases.
|
||||
|
||||
## Support exceeding your expectations
|
||||
|
||||
### :speech_balloon: Community Support
|
||||
Everybody is welcome to visit the [Radzen Community forum](https://forum.radzen.com/). Join the growing community and participate in the discussions!
|
||||
|
||||
### :dart: Dedicated Support
|
||||
|
||||
The Radzen team monitors the forum threads, but does not guarantee a response to every question. For guaranteed responses you may consider the dedicated support option.
|
||||
|
||||
Dedicated support for the Radzen Blazor Components is available as part of the [Radzen Blazor subscription](https://www.radzen.com/pricing).
|
||||
|
||||
Our flagship product [Radzen Blazor Studio](https://www.radzen.com/blazor-studio) provides tons of productivity features for Blazor developers:
|
||||
- An industry-leading WYSIWYG Blazor design time canvas
|
||||
- Scaffolding a complete CRUD applications from a database
|
||||
- Built-in security - authentication and authorization
|
||||
- Visual Studio Code and Professional support
|
||||
- Deployment to IIS and Azure
|
||||
- Dedicated support with 24 hour guaranteed response time
|
||||
- Active community forum
|
||||
|
||||
## Get started with the Radzen Blazor Components
|
||||
## Get started with Radzen Blazor Components
|
||||
|
||||
### Install
|
||||
Check the [getting started](https://blazor.radzen.com/get-started) instructions to start making awesome Blazor applications.
|
||||
|
||||
Radzen Blazor Components are distributed as the Radzen.Blazor nuget package. You can add them to your project in one of the following ways
|
||||
- Install the package from command line by running dotnet add package Radzen.Blazor
|
||||
- Add the project from the Visual Nuget Package Manager
|
||||
- Manually edit the .csproj file and add a project reference
|
||||
## Run demos locally
|
||||
|
||||
### Import the namespace
|
||||
|
||||
Open the `_Imports.razor` file of your Blazor application and add this line `@using Radzen.Blazor`.
|
||||
|
||||
### Include a theme
|
||||
|
||||
Open the `_Host.cshtml` file (server-side Blazor) or `wwwroot/index.html` (client-side Blazor) and include a theme CSS file by adding this snippet `<link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css">` or `<link rel="stylesheet" href="_content/Radzen.Blazor/css/default-base.css">` if you either include Bootstrap manually or don't use it at all.
|
||||
|
||||
### Include Radzen.Blazor.js
|
||||
|
||||
Open the `_Host.cshtml` file (server-side Blazor) or `wwwroot/index.html` (client-side Blazor) and include this snippet `<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>`
|
||||
|
||||
### Use a component
|
||||
Use any Radzen Blazor component by typing its tag name in a Blazor page e.g.
|
||||
```html
|
||||
<RadzenButton Text="Hi"></RadzenButton>
|
||||
```
|
||||
|
||||
#### Data-binding a property
|
||||
```razor
|
||||
<RadzenButton Text=@text />
|
||||
<RadzenTextBox @bind-Value=@text />
|
||||
@code {
|
||||
string text = "Hi";
|
||||
}
|
||||
```
|
||||
|
||||
#### Handing events
|
||||
|
||||
```razor
|
||||
<RadzenButton Click="@ButtonClicked" Text="Hi"></RadzenButton>
|
||||
@code {
|
||||
void ButtonClicked()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
Use **Radzen.Server.sln** to open and run demos as Blazor server application or **Radzen.WebAssembly.sln** to open and run demos as Blazor WebAssembly application. The demos require the .NET 10 SDK and should preferably be opened in VS2026.
|
||||
|
||||
171
Radzen.Blazor.Tests/AIChatTests.cs
Normal file
171
Radzen.Blazor.Tests/AIChatTests.cs
Normal file
@@ -0,0 +1,171 @@
|
||||
using Bunit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Radzen;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class AIChatTests
|
||||
{
|
||||
private void RegisterChatService(TestContext ctx)
|
||||
{
|
||||
// Register a dummy HttpClient and default options for AIChatService
|
||||
ctx.Services.AddSingleton(new HttpClient());
|
||||
ctx.Services.AddScoped<IAIChatService, AIChatService>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldRenderWithDefaultProperties()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>();
|
||||
Assert.Contains("Type your message...", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldRenderWithCustomTitle()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Custom Chat"));
|
||||
Assert.Contains("Custom Chat", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldRenderWithCustomPlaceholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
|
||||
.Add(p => p.Placeholder, "Enter your message here..."));
|
||||
Assert.Contains("Enter your message here...", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldRenderWithCustomEmptyMessage()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
|
||||
.Add(p => p.EmptyMessage, "No messages yet"));
|
||||
Assert.Contains("No messages yet", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldShowClearButtonByDefault()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>();
|
||||
Assert.Contains("rz-chat-header-clear", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldHideClearButtonWhenShowClearButtonIsFalse()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
|
||||
.Add(p => p.ShowClearButton, false));
|
||||
Assert.DoesNotContain("clear_all", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldBeDisabledWhenDisabledIsTrue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
|
||||
.Add(p => p.Disabled, true));
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldBeReadOnlyWhenReadOnlyIsTrue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters
|
||||
.Add(p => p.ReadOnly, true));
|
||||
Assert.Contains("readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldHaveCorrectCssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>();
|
||||
Assert.Contains("rz-chat", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ChatMessage_ShouldHaveCorrectProperties()
|
||||
{
|
||||
// Arrange
|
||||
var message = new ChatMessage
|
||||
{
|
||||
Content = "Test message",
|
||||
IsUser = true,
|
||||
Timestamp = DateTime.Now
|
||||
};
|
||||
// Assert
|
||||
Assert.NotEmpty(message.Id);
|
||||
Assert.Equal("Test message", message.Content);
|
||||
Assert.True(message.IsUser);
|
||||
Assert.False(message.IsStreaming);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_AddMessage_ShouldAddMessageToList()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>();
|
||||
// Act
|
||||
component.Instance.AddMessage("Test message", true);
|
||||
// Assert
|
||||
var messages = component.Instance.GetMessages();
|
||||
Assert.Single(messages);
|
||||
Assert.Equal("Test message", messages[0].Content);
|
||||
Assert.True(messages[0].IsUser);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ClearChat_ShouldRemoveAllMessages()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>();
|
||||
component.Instance.AddMessage("Test message 1", true);
|
||||
component.Instance.AddMessage("Test message 2", false);
|
||||
// Act
|
||||
component.InvokeAsync(async () => await component.Instance.ClearChat()).Wait();
|
||||
// Assert
|
||||
Assert.Empty(component.Instance.GetMessages());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenAIChat_ShouldLimitMessagesToMaxMessages()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
RegisterChatService(ctx);
|
||||
var component = ctx.RenderComponent<RadzenAIChat>(parameters => parameters.Add(p => p.MaxMessages, 3));
|
||||
component.Instance.AddMessage("Message 1", true);
|
||||
component.Instance.AddMessage("Message 2", false);
|
||||
component.Instance.AddMessage("Message 3", true);
|
||||
component.Instance.AddMessage("Message 4", false);
|
||||
// Assert
|
||||
var messages = component.Instance.GetMessages();
|
||||
Assert.Equal(3, messages.Count);
|
||||
Assert.Equal("Message 2", messages[0].Content);
|
||||
Assert.Equal("Message 3", messages[1].Content);
|
||||
Assert.Equal("Message 4", messages[2].Content);
|
||||
}
|
||||
}
|
||||
}
|
||||
195
Radzen.Blazor.Tests/AccordionTests.cs
Normal file
195
Radzen.Blazor.Tests/AccordionTests.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class AccordionTests
|
||||
{
|
||||
[Fact]
|
||||
public void Accordion_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAccordion>();
|
||||
|
||||
Assert.Contains(@"rz-accordion", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_Renders_AccordionItems()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenAccordionItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Test Item");
|
||||
builder.AddAttribute(2, "ChildContent", (RenderFragment)(contentBuilder =>
|
||||
{
|
||||
contentBuilder.AddContent(0, "Item Content");
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("Test Item", component.Markup);
|
||||
Assert.Contains("Item Content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_Renders_ItemWithIcon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenAccordionItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Orders");
|
||||
builder.AddAttribute(2, "Icon", "account_balance_wallet");
|
||||
builder.AddAttribute(3, "ChildContent", (RenderFragment)(contentBuilder =>
|
||||
{
|
||||
contentBuilder.AddContent(0, "Order Details");
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("account_balance_wallet", component.Markup);
|
||||
Assert.Contains("Orders", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_SingleExpand_OnlyOneItemExpanded()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, false); // Single expand mode
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
// Add first item
|
||||
builder.OpenComponent<RadzenAccordionItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Item 1");
|
||||
builder.AddAttribute(2, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content 1")));
|
||||
builder.CloseComponent();
|
||||
|
||||
// Add second item
|
||||
builder.OpenComponent<RadzenAccordionItem>(1);
|
||||
builder.AddAttribute(1, "Text", "Item 2");
|
||||
builder.AddAttribute(2, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content 2")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.False(component.Instance.Multiple);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_MultipleExpand_AllowsMultipleItemsExpanded()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
});
|
||||
|
||||
Assert.True(component.Instance.Multiple);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_Raises_ExpandEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var expandRaised = false;
|
||||
int expandedIndex = -1;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Expand, EventCallback.Factory.Create<int>(this, (index) =>
|
||||
{
|
||||
expandRaised = true;
|
||||
expandedIndex = index;
|
||||
}));
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenAccordionItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Test Item");
|
||||
builder.AddAttribute(2, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Find and click the accordion header link to expand
|
||||
var header = component.Find(".rz-accordion-header a");
|
||||
header.Click();
|
||||
|
||||
Assert.True(expandRaised);
|
||||
Assert.Equal(0, expandedIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_Raises_CollapseEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var collapseRaised = false;
|
||||
int collapsedIndex = -1;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Collapse, EventCallback.Factory.Create<int>(this, (index) =>
|
||||
{
|
||||
collapseRaised = true;
|
||||
collapsedIndex = index;
|
||||
}));
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenAccordionItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Test Item");
|
||||
builder.AddAttribute(2, "Selected", true); // Start expanded
|
||||
builder.AddAttribute(3, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Find and click the accordion header link to collapse
|
||||
var header = component.Find(".rz-accordion-header a");
|
||||
header.Click();
|
||||
|
||||
Assert.True(collapseRaised);
|
||||
Assert.Equal(0, collapsedIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Accordion_DisabledItem_CannotExpand()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var expandRaised = false;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAccordion>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Expand, EventCallback.Factory.Create<int>(this, (_) => expandRaised = true));
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenAccordionItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Disabled Item");
|
||||
builder.AddAttribute(2, "Disabled", true);
|
||||
builder.AddAttribute(3, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Content")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Try to click the disabled item
|
||||
var header = component.Find(".rz-accordion-header a");
|
||||
header.Click();
|
||||
|
||||
// Event should not be raised for disabled item
|
||||
Assert.False(expandRaised);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
195
Radzen.Blazor.Tests/AlertTests.cs
Normal file
195
Radzen.Blazor.Tests/AlertTests.cs
Normal file
@@ -0,0 +1,195 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class AlertTests
|
||||
{
|
||||
[Fact]
|
||||
public void Alert_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
Assert.Contains(@"rz-alert", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Renders_AlertStyle()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Danger));
|
||||
Assert.Contains("rz-danger", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Success));
|
||||
Assert.Contains("rz-success", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Warning));
|
||||
Assert.Contains("rz-warning", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlertStyle, AlertStyle.Info));
|
||||
Assert.Contains("rz-info", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Renders_Shade()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add(p => p.AlertStyle, AlertStyle.Primary)
|
||||
.Add(p => p.Shade, Shade.Lighter));
|
||||
|
||||
Assert.Contains("rz-shade-lighter", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add(p => p.AlertStyle, AlertStyle.Primary)
|
||||
.Add(p => p.Shade, Shade.Darker));
|
||||
|
||||
Assert.Contains("rz-shade-darker", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Renders_Variant()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Outlined));
|
||||
Assert.Contains("rz-variant-outlined", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Flat));
|
||||
Assert.Contains("rz-variant-flat", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Renders_Title()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
var title = "Alert Title";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Title, title));
|
||||
|
||||
Assert.Contains(title, component.Markup);
|
||||
Assert.Contains("rz-alert-title", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Renders_Text()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
var text = "This is an alert message";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(text, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
|
||||
{
|
||||
parameters.AddChildContent("Custom alert content");
|
||||
});
|
||||
|
||||
Assert.Contains("Custom alert content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_ShowIcon_DisplaysIcon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
// Default should show icon
|
||||
Assert.Contains("rz-alert-icon", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ShowIcon, false));
|
||||
Assert.DoesNotContain("rz-alert-icon", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_AllowClose_DisplaysCloseButton()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenAlert>();
|
||||
|
||||
// Default AllowClose is true - should contain a button with close icon
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AllowClose, true));
|
||||
Assert.Contains("close", component.Markup);
|
||||
Assert.Contains("rz-button", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AllowClose, false));
|
||||
// When AllowClose is false, should not have close button
|
||||
var buttonCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-button").Count;
|
||||
Assert.Equal(0, buttonCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_CloseButton_RaisesCloseEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var closeRaised = false;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowClose, true);
|
||||
parameters.Add(p => p.Close, () => closeRaised = true);
|
||||
});
|
||||
|
||||
var closeButton = component.Find("button.rz-button");
|
||||
closeButton.Click();
|
||||
|
||||
Assert.True(closeRaised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_Visible_ControlsDisplay()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Visible, true);
|
||||
parameters.Add(p => p.Text, "Visible Alert");
|
||||
});
|
||||
|
||||
Assert.Contains("Visible Alert", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Visible, false));
|
||||
|
||||
// When not visible, component should not render
|
||||
Assert.DoesNotContain("Visible Alert", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Alert_CloseButton_SetsVisibleToFalse()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var visibleValue = true;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAlert>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Visible, visibleValue);
|
||||
parameters.Add(p => p.AllowClose, true);
|
||||
parameters.Add(p => p.VisibleChanged, (bool value) => visibleValue = value);
|
||||
});
|
||||
|
||||
var closeButton = component.Find("button.rz-button");
|
||||
closeButton.Click();
|
||||
|
||||
Assert.False(visibleValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
139
Radzen.Blazor.Tests/AutoCompleteTests.cs
Normal file
139
Radzen.Blazor.Tests/AutoCompleteTests.cs
Normal file
@@ -0,0 +1,139 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class AutoCompleteTests
|
||||
{
|
||||
[Fact]
|
||||
public void AutoComplete_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenAutoComplete>();
|
||||
|
||||
Assert.Contains(@"rz-autocomplete", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AutoComplete_Renders_InputElement()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenAutoComplete>();
|
||||
|
||||
Assert.Contains("type=\"text\"", component.Markup);
|
||||
Assert.Contains("rz-inputtext", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AutoComplete_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenAutoComplete>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AutoComplete_Renders_Placeholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenAutoComplete>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Placeholder, "Type to search...");
|
||||
});
|
||||
|
||||
Assert.Contains("placeholder=\"Type to search...\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AutoComplete_Renders_WithData()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Apple", "Banana", "Cherry" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenAutoComplete>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-autocomplete-panel", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AutoComplete_Enum_Converts_To_Attr_Value()
|
||||
{
|
||||
// Options
|
||||
Assert.Equal("off", AutoCompleteType.Off.GetAutoCompleteValue());
|
||||
Assert.Equal("on", AutoCompleteType.On.GetAutoCompleteValue());
|
||||
Assert.Equal("name", AutoCompleteType.Name.GetAutoCompleteValue());
|
||||
Assert.Equal("honorific-prefix", AutoCompleteType.HonorificPrefix.GetAutoCompleteValue());
|
||||
Assert.Equal("given-name", AutoCompleteType.GivenName.GetAutoCompleteValue());
|
||||
Assert.Equal("additional-name", AutoCompleteType.AdditionalName.GetAutoCompleteValue());
|
||||
Assert.Equal("family-name", AutoCompleteType.FamilyName.GetAutoCompleteValue());
|
||||
Assert.Equal("honorific-suffix", AutoCompleteType.HonorificSuffix.GetAutoCompleteValue());
|
||||
Assert.Equal("nickname", AutoCompleteType.Nickname.GetAutoCompleteValue());
|
||||
Assert.Equal("email", AutoCompleteType.Email.GetAutoCompleteValue());
|
||||
Assert.Equal("username", AutoCompleteType.Username.GetAutoCompleteValue());
|
||||
Assert.Equal("new-password", AutoCompleteType.NewPassword.GetAutoCompleteValue());
|
||||
Assert.Equal("current-password", AutoCompleteType.CurrentPassword.GetAutoCompleteValue());
|
||||
Assert.Equal("one-time-code", AutoCompleteType.OneTimeCode.GetAutoCompleteValue());
|
||||
Assert.Equal("organization-title", AutoCompleteType.OrganizationTitle.GetAutoCompleteValue());
|
||||
Assert.Equal("organization", AutoCompleteType.Organization.GetAutoCompleteValue());
|
||||
Assert.Equal("street-address", AutoCompleteType.StreetAddress.GetAutoCompleteValue());
|
||||
Assert.Equal("address-line1", AutoCompleteType.AddressLine1.GetAutoCompleteValue());
|
||||
Assert.Equal("address-line2", AutoCompleteType.AddressLine2.GetAutoCompleteValue());
|
||||
Assert.Equal("address-line3", AutoCompleteType.AddressLine3.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level1", AutoCompleteType.AddressLevel1.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level2", AutoCompleteType.AddressLevel2.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level3", AutoCompleteType.AddressLevel3.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level4", AutoCompleteType.AddressLevel4.GetAutoCompleteValue());
|
||||
Assert.Equal("country", AutoCompleteType.Country.GetAutoCompleteValue());
|
||||
Assert.Equal("country-name", AutoCompleteType.CountryName.GetAutoCompleteValue());
|
||||
Assert.Equal("postal-code", AutoCompleteType.PostalCode.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-name", AutoCompleteType.CcName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-given-name", AutoCompleteType.CcGivenName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-additional-name", AutoCompleteType.CcAdditionalName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-family-name", AutoCompleteType.CcFamilyName.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-number", AutoCompleteType.CcNumber.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-exp", AutoCompleteType.CcExp.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-exp-month", AutoCompleteType.CcExpMonth.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-exp-year", AutoCompleteType.CcExpYear.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-csc", AutoCompleteType.CcCsc.GetAutoCompleteValue());
|
||||
Assert.Equal("cc-type", AutoCompleteType.CcType.GetAutoCompleteValue());
|
||||
Assert.Equal("transaction-currency", AutoCompleteType.TransactionCurrency.GetAutoCompleteValue());
|
||||
Assert.Equal("transaction-amount", AutoCompleteType.TransactionAmount.GetAutoCompleteValue());
|
||||
Assert.Equal("language", AutoCompleteType.Language.GetAutoCompleteValue());
|
||||
Assert.Equal("bday", AutoCompleteType.Bday.GetAutoCompleteValue());
|
||||
Assert.Equal("bday-day", AutoCompleteType.BdayDay.GetAutoCompleteValue());
|
||||
Assert.Equal("bday-month", AutoCompleteType.BdayMonth.GetAutoCompleteValue());
|
||||
Assert.Equal("bday-year", AutoCompleteType.BdayYear.GetAutoCompleteValue());
|
||||
Assert.Equal("sex", AutoCompleteType.Sex.GetAutoCompleteValue());
|
||||
Assert.Equal("tel", AutoCompleteType.Tel.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-country-code", AutoCompleteType.TelCountryCode.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-national", AutoCompleteType.TelNational.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-area-code", AutoCompleteType.TelAreaCode.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-local", AutoCompleteType.TelLocal.GetAutoCompleteValue());
|
||||
Assert.Equal("tel-extension", AutoCompleteType.TelExtension.GetAutoCompleteValue());
|
||||
Assert.Equal("impp", AutoCompleteType.Impp.GetAutoCompleteValue());
|
||||
Assert.Equal("url", AutoCompleteType.Url.GetAutoCompleteValue());
|
||||
Assert.Equal("photo", AutoCompleteType.Photo.GetAutoCompleteValue());
|
||||
// Synonyms
|
||||
Assert.Equal("address-level1", AutoCompleteType.State.GetAutoCompleteValue());
|
||||
Assert.Equal("address-level1", AutoCompleteType.Province.GetAutoCompleteValue());
|
||||
Assert.Equal("postal-code", AutoCompleteType.ZipCode.GetAutoCompleteValue());
|
||||
Assert.Equal("given-name", AutoCompleteType.FirstName.GetAutoCompleteValue());
|
||||
Assert.Equal("additional-name", AutoCompleteType.MiddleName.GetAutoCompleteValue());
|
||||
Assert.Equal("family-name", AutoCompleteType.LastName.GetAutoCompleteValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
47
Radzen.Blazor.Tests/BadgeTests.cs
Normal file
47
Radzen.Blazor.Tests/BadgeTests.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class BadgeTests
|
||||
{
|
||||
[Fact]
|
||||
public void Badge_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBadge>();
|
||||
|
||||
var text = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(text, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Badge_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBadge>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddChildContent("SomeContent"));
|
||||
|
||||
Assert.Contains(@$"SomeContent", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Badge_Renders_BadgeStyle()
|
||||
{
|
||||
var badgeStyle = BadgeStyle.Danger;
|
||||
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBadge>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.BadgeStyle, badgeStyle));
|
||||
|
||||
Assert.Contains($"badge-{badgeStyle.ToString().ToLower()}", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
77
Radzen.Blazor.Tests/BreadCrumbTests.cs
Normal file
77
Radzen.Blazor.Tests/BreadCrumbTests.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class BreadCrumbTests
|
||||
{
|
||||
[Fact]
|
||||
public void BreadCrumb_Renders_Items()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBreadCrumb>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(c => c.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenBreadCrumbItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
//@"<RadzenBreadCrumbItem Text=""Test"" />"
|
||||
Assert.Contains(@"class=""rz-breadcrumb-item", component.Markup);
|
||||
Assert.Contains(">Test</", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BreadCrumb_Renders_Icon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBreadCrumb>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(c => c.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenBreadCrumbItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
|
||||
builder.AddAttribute(2, nameof(RadzenBreadCrumbItem.Icon), "add");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
//@"<RadzenBreadCrumbItem Text=""Test"" />"
|
||||
Assert.Contains("<i", component.Markup);
|
||||
Assert.Contains(">add</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BreadCrumb_Renders_Link()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenBreadCrumb>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(c => c.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenBreadCrumbItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenBreadCrumbItem.Text), "Test");
|
||||
builder.AddAttribute(2, nameof(RadzenBreadCrumbItem.Icon), "add");
|
||||
builder.AddAttribute(3, nameof(RadzenBreadCrumbItem.Path), "/badge");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
//@"<RadzenBreadCrumbItem Text=""Test"" />"
|
||||
Assert.Contains("<i", component.Markup);
|
||||
Assert.Contains(">add</i>", component.Markup);
|
||||
Assert.Contains("<a href=\"/badge", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
217
Radzen.Blazor.Tests/ButtonTests.cs
Normal file
217
Radzen.Blazor.Tests/ButtonTests.cs
Normal file
@@ -0,0 +1,217 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ButtonTests
|
||||
{
|
||||
[Fact]
|
||||
public void Button_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var text = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_BusySpinner()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add(p => p.Icon, icon)
|
||||
.Add(p => p.IsBusy, true)
|
||||
);
|
||||
|
||||
// does not render the actual icon when busy
|
||||
Assert.DoesNotContain(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
|
||||
// renders the icon with busy spin animation
|
||||
Assert.Contains(@"<i style=""animation: rotation", component.Markup);
|
||||
Assert.Contains(">refresh</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_IconAndTextParameters()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var text = "Test";
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_ImageParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var image = "test.png";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Image, image));
|
||||
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""button"" />", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_ImageAndTextParameters()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var text = "Test";
|
||||
var image = "test.png";
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Image, image);
|
||||
parameters.Add(p => p.ImageAlternateText, text);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_SizeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, ButtonSize.Medium));
|
||||
|
||||
Assert.Contains(@$"rz-button-md", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, ButtonSize.Small));
|
||||
|
||||
Assert.Contains(@$"rz-button-sm", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Primary));
|
||||
|
||||
Assert.Contains(@$"rz-primary", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonStyle, ButtonStyle.Secondary));
|
||||
|
||||
Assert.Contains(@$"rz-secondary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_TypeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonType, ButtonType.Button));
|
||||
|
||||
Assert.Contains(@$"type=""button""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonType, ButtonType.Submit));
|
||||
|
||||
Assert.Contains(@$"type=""submit""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ButtonType, ButtonType.Reset));
|
||||
|
||||
Assert.Contains(@$"type=""reset""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddChildContent("SomeContent"));
|
||||
|
||||
Assert.Contains(@$"SomeContent", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Button_Raises_ClickEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenButton>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Click, args => { clicked = true; }));
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
Radzen.Blazor.Tests/CardTests.cs
Normal file
46
Radzen.Blazor.Tests/CardTests.cs
Normal file
@@ -0,0 +1,46 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class CardTests
|
||||
{
|
||||
[Fact]
|
||||
public void Card_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCard>();
|
||||
|
||||
Assert.Contains(@"rz-card", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Card_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCard>(parameters =>
|
||||
{
|
||||
parameters.AddChildContent("<div>Card Content</div>");
|
||||
});
|
||||
|
||||
Assert.Contains("Card Content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Card_Renders_Variant()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCard>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Outlined));
|
||||
Assert.Contains("rz-variant-outlined", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Filled));
|
||||
Assert.Contains("rz-variant-filled", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, Variant.Flat));
|
||||
Assert.Contains("rz-variant-flat", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
173
Radzen.Blazor.Tests/CarouselTests.cs
Normal file
173
Radzen.Blazor.Tests/CarouselTests.cs
Normal file
@@ -0,0 +1,173 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class CarouselTests
|
||||
{
|
||||
[Fact]
|
||||
public void Carousel_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCarousel>();
|
||||
|
||||
Assert.Contains(@"rz-carousel", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_AllowPaging_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenCarouselItem>(0);
|
||||
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide 1")));
|
||||
builder.CloseComponent();
|
||||
|
||||
builder.OpenComponent<RadzenCarouselItem>(2);
|
||||
builder.AddAttribute(3, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide 2")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("rz-carousel-pager-button", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_AllowPaging_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, false);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenCarouselItem>(0);
|
||||
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide 1")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-carousel-pager-button", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_AllowNavigation_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowNavigation, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-carousel-prev", component.Markup);
|
||||
Assert.Contains("rz-carousel-next", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_AllowNavigation_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowNavigation, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-carousel-prev", component.Markup);
|
||||
Assert.DoesNotContain("rz-carousel-next", component.Markup);
|
||||
Assert.Contains("rz-carousel-no-navigation", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_PagerPosition_Top()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.PagerPosition, PagerPosition.Top);
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenCarouselItem>(0);
|
||||
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("rz-carousel-pager-top", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_PagerPosition_Bottom()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.PagerPosition, PagerPosition.Bottom);
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenCarouselItem>(0);
|
||||
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("rz-carousel-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_PagerPosition_TopAndBottom()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenCarouselItem>(0);
|
||||
builder.AddAttribute(1, "ChildContent", (RenderFragment)(b => b.AddContent(0, "Slide")));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("rz-carousel-pager-top", component.Markup);
|
||||
Assert.Contains("rz-carousel-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_PagerOverlay_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.PagerOverlay, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-carousel-pager-overlay", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Carousel_Renders_PagerOverlay_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCarousel>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.PagerOverlay, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-carousel-pager-overlay", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
Radzen.Blazor.Tests/ChartTests.cs
Normal file
58
Radzen.Blazor.Tests/ChartTests.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Bunit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Radzen.Blazor.Tests;
|
||||
|
||||
public class ChartTests
|
||||
{
|
||||
private readonly ITestOutputHelper output;
|
||||
public ChartTests(ITestOutputHelper output)
|
||||
{
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
[Fact(Timeout = 30000)]
|
||||
public async Task Chart_Tooltip_Performance()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.Setup<Rect>("Radzen.createChart", _ => true).SetResult(new Rect {Left = 0, Top = 0, Width = 200, Height = 200});
|
||||
ctx.Services.AddScoped<TooltipService>();
|
||||
ctx.JSInterop.SetupVoid("Radzen.openChartTooltip", _ => true);
|
||||
ctx.RenderComponent<RadzenChartTooltip>();
|
||||
|
||||
var seriesData = Enumerable.Range(0, 5000).Select(i => new Point { X = i, Y = i });
|
||||
var chart = ctx.RenderComponent<RadzenChart>(chartParameters =>
|
||||
chartParameters
|
||||
.AddChildContent<RadzenLineSeries<Point>>(seriesParameters =>
|
||||
seriesParameters
|
||||
.Add(p => p.CategoryProperty, nameof(Point.X))
|
||||
.Add(p => p.ValueProperty, nameof(Point.Y))
|
||||
.Add(p => p.Data, seriesData))
|
||||
.AddChildContent<RadzenCategoryAxis>(axisParameters =>
|
||||
axisParameters
|
||||
.Add(p => p.Step, 100)
|
||||
.Add(p => p.Formatter, x =>
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
return $"{x}";
|
||||
})));
|
||||
|
||||
var stopwatch = Stopwatch.StartNew();
|
||||
foreach (var invocation in Enumerable.Range(0, 10))
|
||||
{
|
||||
await chart.InvokeAsync(() => chart.Instance.MouseMove(100, 80));
|
||||
Assert.Equal((invocation + 1) * 2, ctx.JSInterop.Invocations.Count(x => x.Identifier == "Radzen.openChartTooltip"));
|
||||
await chart.InvokeAsync(() => chart.Instance.MouseMove(0, 0));
|
||||
Assert.Equal(invocation + 1, ctx.JSInterop.Invocations.Count(x => x.Identifier == "Radzen.closeTooltip"));
|
||||
}
|
||||
output.WriteLine($"Time took: {stopwatch.Elapsed}");
|
||||
}
|
||||
}
|
||||
369
Radzen.Blazor.Tests/ChatTests.cs
Normal file
369
Radzen.Blazor.Tests/ChatTests.cs
Normal file
@@ -0,0 +1,369 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Radzen.Blazor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ChatTests
|
||||
{
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldRenderWithTitle()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
);
|
||||
|
||||
Assert.Contains("Test Chat", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowEmptyMessageWhenNoMessages()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.EmptyMessage, "No messages yet!")
|
||||
);
|
||||
|
||||
Assert.Contains("No messages yet!", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldDisplayMessages()
|
||||
{
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Content = "Hello", UserId = "user1", Timestamp = DateTime.Now },
|
||||
new ChatMessage { Content = "Hi there!", UserId = "user2", Timestamp = DateTime.Now }
|
||||
};
|
||||
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" },
|
||||
new ChatUser { Id = "user2", Name = "Jane" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, messages)
|
||||
);
|
||||
|
||||
Assert.Contains("Hello", component.Markup);
|
||||
Assert.Contains("Hi there!", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowUsersInHeader()
|
||||
{
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" },
|
||||
new ChatUser { Id = "user2", Name = "Jane" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ShowUsers, true)
|
||||
);
|
||||
|
||||
Assert.Contains("John", component.Markup);
|
||||
Assert.Contains("Jane", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowUserNamesAboveMessages()
|
||||
{
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Content = "Hello", UserId = "user2", Timestamp = DateTime.Now }
|
||||
};
|
||||
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" },
|
||||
new ChatUser { Id = "user2", Name = "Jane" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, messages)
|
||||
.Add(p => p.ShowUserNames, true)
|
||||
);
|
||||
|
||||
Assert.Contains("Jane", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowClearButtonWhenEnabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ShowClearButton, true)
|
||||
);
|
||||
|
||||
var clearButton = component.Find(".rz-chat-header-clear");
|
||||
Assert.NotNull(clearButton);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldNotShowClearButtonWhenDisabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ShowClearButton, false)
|
||||
);
|
||||
|
||||
var clearButton = component.FindAll(".rz-chat-header-clear");
|
||||
Assert.Empty(clearButton);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldLimitVisibleUsers()
|
||||
{
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" },
|
||||
new ChatUser { Id = "user2", Name = "Jane" },
|
||||
new ChatUser { Id = "user3", Name = "Bob" },
|
||||
new ChatUser { Id = "user4", Name = "Alice" },
|
||||
new ChatUser { Id = "user5", Name = "Charlie" },
|
||||
new ChatUser { Id = "user6", Name = "David" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ShowUsers, true)
|
||||
.Add(p => p.MaxVisibleUsers, 3)
|
||||
);
|
||||
|
||||
// Should show "+3" for the remaining users
|
||||
Assert.Contains("+3", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowUserMessagesOnRight()
|
||||
{
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Content = "My message", UserId = "user1", Timestamp = DateTime.Now }
|
||||
};
|
||||
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, messages)
|
||||
);
|
||||
|
||||
var userMessage = component.Find(".rz-chat-message-user");
|
||||
Assert.NotNull(userMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowUserMessagesOnLeft()
|
||||
{
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Content = "Other message", UserId = "user2", Timestamp = DateTime.Now }
|
||||
};
|
||||
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" },
|
||||
new ChatUser { Id = "user2", Name = "Jane" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, messages)
|
||||
);
|
||||
|
||||
var participantMessage = component.Find(".rz-chat-message-participant");
|
||||
Assert.NotNull(participantMessage);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowAvatarInitials()
|
||||
{
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John Doe" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ShowUsers, true)
|
||||
);
|
||||
|
||||
Assert.Contains("JD", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowAvatarImageWhenProvided()
|
||||
{
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John", AvatarUrl = "https://example.com/avatar.jpg" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ShowUsers, true)
|
||||
);
|
||||
|
||||
var avatarImage = component.Find(".rz-chat-participant-image");
|
||||
Assert.NotNull(avatarImage);
|
||||
Assert.Equal("https://example.com/avatar.jpg", avatarImage.GetAttribute("src"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldBeDisabledWhenDisabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.Disabled, true)
|
||||
);
|
||||
|
||||
var textarea = component.Find(".rz-chat-textarea");
|
||||
Assert.True(textarea.HasAttribute("disabled"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldBeReadOnlyWhenReadOnly()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.ReadOnly, true)
|
||||
);
|
||||
|
||||
var textarea = component.Find(".rz-chat-textarea");
|
||||
Assert.True(textarea.HasAttribute("readonly"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowCustomPlaceholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, new List<ChatUser>())
|
||||
.Add(p => p.Messages, new List<ChatMessage>())
|
||||
.Add(p => p.Placeholder, "Custom placeholder")
|
||||
);
|
||||
|
||||
var textarea = component.Find(".rz-chat-textarea");
|
||||
Assert.Equal("Custom placeholder", textarea.GetAttribute("placeholder"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowStreamingIndicator()
|
||||
{
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Content = "Streaming message", UserId = "user1", IsStreaming = true, Timestamp = DateTime.Now }
|
||||
};
|
||||
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, messages)
|
||||
);
|
||||
|
||||
var streamingIcon = component.Find(".rz-chat-message-streaming-icon");
|
||||
Assert.NotNull(streamingIcon);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenChat_ShouldShowMessageTimestamps()
|
||||
{
|
||||
var timestamp = DateTime.Now.AddHours(-1);
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new ChatMessage { Content = "Test message", UserId = "user1", Timestamp = timestamp }
|
||||
};
|
||||
|
||||
var users = new List<ChatUser>
|
||||
{
|
||||
new ChatUser { Id = "user1", Name = "John" }
|
||||
};
|
||||
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenChat>(parameters => parameters
|
||||
.Add(p => p.Title, "Test Chat")
|
||||
.Add(p => p.CurrentUserId, "user1")
|
||||
.Add(p => p.Users, users)
|
||||
.Add(p => p.Messages, messages)
|
||||
);
|
||||
|
||||
Assert.Contains(timestamp.ToString("HH:mm"), component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
168
Radzen.Blazor.Tests/CheckBoxListTests.cs
Normal file
168
Radzen.Blazor.Tests/CheckBoxListTests.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class CheckBoxListTests
|
||||
{
|
||||
class Item
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>();
|
||||
|
||||
Assert.Contains(@"rz-checkbox-list", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_WithData()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var data = new List<string> { "Option 1", "Option 2", "Option 3" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("Option 1", component.Markup);
|
||||
Assert.Contains("Option 2", component.Markup);
|
||||
Assert.Contains("Option 3", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_WithCustomTextValueProperties()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var data = new List<Item>
|
||||
{
|
||||
new Item { Id = 1, Name = "First" },
|
||||
new Item { Id = 2, Name = "Second" }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, "Name");
|
||||
parameters.Add(p => p.ValueProperty, "Id");
|
||||
});
|
||||
|
||||
Assert.Contains("First", component.Markup);
|
||||
Assert.Contains("Second", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_Orientation_Horizontal()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Horizontal);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-flex-row", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_Orientation_Vertical()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Vertical);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-flex-column", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_AllowSelectAll()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var data = new List<string> { "Option 1", "Option 2" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowSelectAll, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-multiselect-header", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_SelectAllText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var data = new List<string> { "Option 1", "Option 2" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowSelectAll, true);
|
||||
parameters.Add(p => p.SelectAllText, "Select All Options");
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("Select All Options", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_CheckboxInputs()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var data = new List<string> { "Option 1", "Option 2" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("type=\"checkbox\"", component.Markup);
|
||||
Assert.Contains("rz-chkbox", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBoxList_Renders_DisabledItems()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var data = new List<Item>
|
||||
{
|
||||
new Item { Id = 1, Name = "Enabled", Disabled = false },
|
||||
new Item { Id = 2, Name = "Disabled", Disabled = true }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBoxList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, "Name");
|
||||
parameters.Add(p => p.ValueProperty, "Id");
|
||||
parameters.Add(p => p.DisabledProperty, "Disabled");
|
||||
});
|
||||
|
||||
Assert.Contains("Enabled", component.Markup);
|
||||
Assert.Contains("Disabled", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
242
Radzen.Blazor.Tests/CheckBoxTests.cs
Normal file
242
Radzen.Blazor.Tests/CheckBoxTests.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using Bunit;
|
||||
using Bunit.JSInterop;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class CheckBoxTests
|
||||
{
|
||||
[Fact]
|
||||
public void CheckBox_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-chkbox", component.Markup);
|
||||
Assert.Contains(@$"rz-chkbox-box", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool?>>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool?>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
Assert.Contains(@$"rzi-check", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool?>(p => p.Value, !value));
|
||||
|
||||
Assert.DoesNotContain(@$"rz-state-active", component.Markup);
|
||||
Assert.DoesNotContain(@$"rzi-check", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool?>(p => p.Value, null));
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
Assert.Contains(@$"rzi-times", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_NameParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Name, value));
|
||||
|
||||
Assert.Contains(@$"name=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"disabled", component.Markup);
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Raises_ChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Raises_ValueChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_TriStateParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool?>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.TriState, true));
|
||||
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
Assert.Contains(@$"rzi-check", component.Markup);
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.DoesNotContain(@$"rz-state-active", component.Markup);
|
||||
Assert.DoesNotContain(@$"rzi-check", component.Markup);
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
Assert.Contains(@$"rzi-times", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_Renders_ReadonlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, true));
|
||||
|
||||
Assert.Contains(@$"readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_DoesNotRaise_ChangedEvent_ReadonlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add<bool>(p => p.ReadOnly, true)
|
||||
.Add(p => p.Change, args => { raised = true; })
|
||||
);
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_DoesNotRaise_ValueChangedEvent_ReadonlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add<bool>(p => p.ReadOnly, true)
|
||||
.Add(p => p.ValueChanged, args => { raised = true; })
|
||||
);
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CheckBox_ValueNotChanged_ReadonlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenCheckBox<bool>>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add<bool>(p => p.ReadOnly, true)
|
||||
.Add<bool>(p => p.Value, value)
|
||||
);
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.Contains(@$"rz-state-active", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters
|
||||
.Add<bool>(p => p.ReadOnly, !true)
|
||||
.Add<bool>(p => p.Value, value)
|
||||
);
|
||||
|
||||
component.Find("div.rz-chkbox-box").Click();
|
||||
|
||||
Assert.DoesNotContain(@$"rz-state-active", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Radzen.Blazor.Tests/ColorPickerTests.cs
Normal file
16
Radzen.Blazor.Tests/ColorPickerTests.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ColorPickerTests
|
||||
{
|
||||
[Fact]
|
||||
public void ColorPicker_ShouldAcceptInvalidValues()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenColorPicker>(ComponentParameter.CreateParameter("Value", "invalid"));
|
||||
}
|
||||
}
|
||||
}
|
||||
74
Radzen.Blazor.Tests/ColumnTests.cs
Normal file
74
Radzen.Blazor.Tests/ColumnTests.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ColumnTests
|
||||
{
|
||||
[Fact]
|
||||
public void Column_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenColumn>();
|
||||
|
||||
Assert.Contains(@"rz-col", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Column_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenColumn>(parameters =>
|
||||
{
|
||||
parameters.AddChildContent("<div>Column Content</div>");
|
||||
});
|
||||
|
||||
Assert.Contains("Column Content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Column_Renders_SizeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenColumn>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, 6));
|
||||
|
||||
Assert.Contains("rz-col-6", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Column_Renders_SizeMD()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenColumn>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.SizeMD, 4));
|
||||
|
||||
Assert.Contains("rz-col-md-4", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Column_Renders_SizeSM()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenColumn>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.SizeSM, 12));
|
||||
|
||||
Assert.Contains("rz-col-sm-12", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Column_Renders_Offset()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenColumn>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Offset, 2));
|
||||
|
||||
Assert.Contains("rz-offset-2", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3042
Radzen.Blazor.Tests/DataGridTests.cs
Normal file
3042
Radzen.Blazor.Tests/DataGridTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
314
Radzen.Blazor.Tests/DataListTests.cs
Normal file
314
Radzen.Blazor.Tests/DataListTests.cs
Normal file
@@ -0,0 +1,314 @@
|
||||
using Bunit;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class DataListTests
|
||||
{
|
||||
[Fact]
|
||||
public void DataList_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1,2,3}));
|
||||
|
||||
Assert.Contains(@$"rz-datalist-content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Renders_AllowPagingParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowPaging, true));
|
||||
|
||||
Assert.Contains(@$"rz-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Renders_PagerPositionTopParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Renders_PagerPositionTopAndBottomParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
Assert.Contains(@$"rz-pager-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Renders_PagerDensityDefault()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
parameters.Add<Density>(p => p.Density, Density.Default);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-density-compact", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Renders_PagerDensityCompact()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<PagerPosition>(p => p.PagerPosition, PagerPosition.Top);
|
||||
parameters.Add<Density>(p => p.Density, Density.Compact);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-density-compact", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Renders_WrapItemsParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, new[] { 1, 2, 3 }));
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.WrapItems, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-g", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Raises_LoadDataEventOnNextPageClick()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 10);
|
||||
Assert.True(newArgs.Top == 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Raises_LoadDataEventOnLastPageClick()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 90);
|
||||
Assert.True(newArgs.Top == 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Raises_LoadDataEventOnPrevPageClick()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-next").Click();
|
||||
component.Find(".rz-pager-prev").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 0);
|
||||
Assert.True(newArgs.Top == 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Raises_LoadDataEventOnFirstPageClick()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-next").Click();
|
||||
component.Find(".rz-pager-first").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 0);
|
||||
Assert.True(newArgs.Top == 10);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_NotRaises_LoadDataEventOnFirstPageClickWhenOnFirstPage()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-first").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_NotRaises_LoadDataEventOnPrevPageClickWhenOnFirstPage()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-prev").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_NotRaises_LoadDataEventOnLastPageClickWhenOnLastPage()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_NotRaises_LoadDataEventOnNextPageClickWhenOnLastPage()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-last").Click();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DataList_Respects_PageSizeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDataList<int>>(parameterBuilder => parameterBuilder.Add<IEnumerable<int>>(p => p.Data, Enumerable.Range(0, 100)));
|
||||
|
||||
var raised = false;
|
||||
LoadDataArgs newArgs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.AllowPaging, true);
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<LoadDataArgs>(p => p.LoadData, args => { raised = true; newArgs = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-pager-next").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(newArgs.Skip == 20);
|
||||
Assert.True(newArgs.Top == 20);
|
||||
}
|
||||
}
|
||||
}
|
||||
861
Radzen.Blazor.Tests/DatePickerTests.cs
Normal file
861
Radzen.Blazor.Tests/DatePickerTests.cs
Normal file
@@ -0,0 +1,861 @@
|
||||
using Bunit;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class DatePickerTests
|
||||
{
|
||||
[Fact]
|
||||
public void DatePicker_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
Assert.Contains(@$"rz-datepicker", component.Markup);
|
||||
Assert.Contains(@$"rz-calendar", component.Markup);
|
||||
Assert.Contains(@$"rz-calendar-header", component.Markup);
|
||||
Assert.Contains(@$"rz-calendar-view", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_ShowTimeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ShowTime, true));
|
||||
|
||||
Assert.Contains(@$"rz-timepicker", component.Markup);
|
||||
Assert.Contains(@$"rz-hour-picker", component.Markup);
|
||||
Assert.Contains(@$"rz-minute-picker", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_ShowSecondsParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.ShowTime, true);
|
||||
parameters.Add<bool>(p => p.ShowSeconds, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-timepicker", component.Markup);
|
||||
Assert.Contains(@$"rz-hour-picker", component.Markup);
|
||||
Assert.Contains(@$"rz-minute-picker", component.Markup);
|
||||
Assert.Contains(@$"rz-second-picker", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_ShowTimeOkButtonParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.ShowTime, true);
|
||||
parameters.Add<bool>(p => p.ShowTimeOkButton, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-timepicker", component.Markup);
|
||||
Assert.Contains(@$"rz-hour-picker", component.Markup);
|
||||
Assert.Contains(@$"rz-minute-picker", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">Ok</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_DateFormatParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var format = "d";
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.DateFormat, format);
|
||||
parameters.Add<object>(p => p.Value, DateTime.Now);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"value=""{string.Format("{0:" + format + "}", DateTime.Now)}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_HourFormatParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.ShowTime, true);
|
||||
parameters.Add(p => p.HourFormat, "12");
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-ampm-picker", component.Markup);
|
||||
Assert.Contains(@$"rzi-chevron-up", component.Markup);
|
||||
Assert.Contains(@$"rzi-chevron-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_TimeOnlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.ShowTime, true);
|
||||
parameters.Add<bool>(p => p.TimeOnly, true);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-calendar-header", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_AllowClearParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<object>(p => p.Value, DateTime.Now);
|
||||
parameters.Add<bool>(p => p.AllowClear, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rz-dropdown-clear-icon rzi rzi-times""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_TabIndexParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var value = 1;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.TabIndex, value));
|
||||
|
||||
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_EmptyCssClass_WhenValueIsEmpty()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, null));
|
||||
|
||||
Assert.Contains(@$"rz-state-empty", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_DoesNotRender_EmptyCssClass_WhenValueIsNotEmpty()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, DateTime.Now));
|
||||
|
||||
Assert.DoesNotContain(@$"rz-state-empty", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"disabled", component.Markup);
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_ReadOnlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, value));
|
||||
|
||||
Assert.Contains(@$"readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_NotRaises_ChangeEventOnNextMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-calendar-next-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_NotRaises_ValueChangedEventOnNextMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-calendar-next-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_NotRaises_ChangeEventOnPrevMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-calendar-prev-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_NotRaises_ValueChangedEventOnPrevMonth()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-calendar-prev-icon").Click();
|
||||
|
||||
Assert.False(raised);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Raises_ValueChangedEvent_Returns_PreviousDateOnInputOnDisabledDates()
|
||||
{
|
||||
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
|
||||
DateTime previousDay = DateTime.Today.AddDays(-1);
|
||||
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
|
||||
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
|
||||
});
|
||||
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
|
||||
// initialize DateTimeValue
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
|
||||
inputElement.Change(previousDay.AddDays(-1));
|
||||
|
||||
// try to enter disabled date
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
|
||||
inputElement.Change(DateTime.Today);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Equal(previousDay, (DateTime)newValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Clears_InputOnDisabledDates()
|
||||
{
|
||||
IEnumerable<DateTime> dates = new DateTime[] { DateTime.Today };
|
||||
DateTime previousDay = DateTime.Today.AddDays(-1);
|
||||
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; })
|
||||
.Add(p => p.DateRender, args => { args.Disabled = dates.Contains(args.Date); });
|
||||
});
|
||||
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
|
||||
// initialize DateTimeValue
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(previousDay.ToShortDateString());
|
||||
inputElement.Change(previousDay.AddDays(-1));
|
||||
|
||||
// try to enter disabled date
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(DateTime.Today.ToShortDateString());
|
||||
inputElement.Change(DateTime.Today);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Null(newValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Parses_Input_Using_DateFormat()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.DateFormat, "ddMM");
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
|
||||
string input = "3012";
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
|
||||
inputElement.Change(input);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Parses_Input_Using_ParseInput()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime?>>();
|
||||
|
||||
Func<string, DateTime?> customParseInput = (input) =>
|
||||
{
|
||||
if (DateTime.TryParseExact(input, "ddMM", null, DateTimeStyles.None, out var result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ParseInput, customParseInput);
|
||||
parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
|
||||
string input = "3012";
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(input);
|
||||
inputElement.Change(input);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Equal(new DateTime(DateTime.Now.Year, 12, 30), newValue);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Respects_DateTimeMaxValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, DateTime.MaxValue);
|
||||
});
|
||||
|
||||
Assert.Contains(DateTime.MaxValue.ToString(component.Instance.DateFormat), component.Markup);
|
||||
|
||||
var exception = Record.Exception(() => component.Find(".rz-calendar-next-icon")
|
||||
.Click());
|
||||
Assert.Null(exception);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(DateTimeKind.Local)]
|
||||
[InlineData(DateTimeKind.Unspecified)]
|
||||
[InlineData(DateTimeKind.Utc)]
|
||||
public void DatePicker_Respects_DateTimeKind(DateTimeKind kind)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(x => x.Kind, kind);
|
||||
parameters.Add(x => x.ShowTime, true);
|
||||
});
|
||||
|
||||
var raised = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-calendar-next-icon").Click();
|
||||
component.FindAll(".rz-button-text").First(x => x.TextContent == "Ok").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.Equal(kind, ((DateTime)newValue).Kind);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Renders_FooterTemplate()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
string actionsTemplate = "<input type=\"button\" value=\"Test\" />";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, DateTime.MinValue);
|
||||
parameters.Add(p => p.FooterTemplate, actionsTemplate);
|
||||
});
|
||||
|
||||
Assert.Contains(actionsTemplate, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Converts_DateTimeOffSet_FromUtc_ToLocal()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var valueUtc = DateTimeOffset.UtcNow;
|
||||
var kind = DateTimeKind.Local;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Kind, kind);
|
||||
parameters.Add(p => p.Value, valueUtc);
|
||||
});
|
||||
|
||||
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
|
||||
Assert.Equal(valueUtc.LocalDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Converts_DateTimeOffSet_Local_ToUtc()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var valueUtc = DateTimeOffset.Now;
|
||||
var kind = DateTimeKind.Utc;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTimeOffset>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Kind, kind);
|
||||
parameters.Add(p => p.Value, valueUtc);
|
||||
});
|
||||
|
||||
Assert.Equal(kind, (component.Instance.Value as DateTime?)?.Kind);
|
||||
Assert.Equal(valueUtc.UtcDateTime.ToString(CultureInfo.InvariantCulture), (component.Instance.Value as DateTime?)?.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Displays_Calender_Icon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>();
|
||||
|
||||
Assert.Contains(@$"rzi-calendar", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Displays_Schedule_Icon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TimeOnly, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rzi-time", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Supports_DateOnly()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
DateOnly? dateOnly = new DateOnly(2024, 1, 31);
|
||||
DateOnly? valueChangedValue = null!;
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateOnly?>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, dateOnly);
|
||||
parameters.Add(p => p.ValueChanged, args => { valueChangedValue = args; });
|
||||
});
|
||||
|
||||
Assert.False(component.Instance.ShowTime);
|
||||
var input = component.Find("input");
|
||||
input.GetAttribute("value").MarkupMatches(dateOnly.ToString());
|
||||
|
||||
// update to new value
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
DateOnly? enteredValue = new DateOnly(2024, 2, 28);
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(enteredValue.Value.ToShortDateString());
|
||||
inputElement.Change(enteredValue);
|
||||
|
||||
input.GetAttribute("value").MarkupMatches(enteredValue.ToString());
|
||||
Assert.Equal(enteredValue, component.Instance.Value);
|
||||
Assert.Equal(enteredValue, valueChangedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Supports_TimeOnly()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
TimeOnly? timeOnly = new TimeOnly(23, 59, 59);
|
||||
TimeOnly? valueChangedValue = null!;
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<TimeOnly>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, timeOnly);
|
||||
parameters.Add(p => p.ValueChanged, args => { valueChangedValue = args; });
|
||||
});
|
||||
|
||||
Assert.True(component.Instance.TimeOnly);
|
||||
Assert.True(component.Instance.ShowTime);
|
||||
var input = component.Find("input");
|
||||
input.GetAttribute("value").MarkupMatches(timeOnly.ToString());
|
||||
|
||||
// update to new value
|
||||
var inputElement = component.Find(".rz-inputtext");
|
||||
TimeOnly? enteredValue = new TimeOnly(1, 4, 5);
|
||||
ctx.JSInterop.Setup<string>("Radzen.getInputValue", invocation => true).SetResult(enteredValue.Value.ToLongTimeString());
|
||||
inputElement.Change(enteredValue);
|
||||
|
||||
input.GetAttribute("value").MarkupMatches(enteredValue.ToString());
|
||||
Assert.Equal(enteredValue, component.Instance.Value);
|
||||
Assert.Equal(enteredValue, valueChangedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_ShowCalendarWeek_WeekNumberAddedInAdditionalColumn()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
|
||||
{
|
||||
parameter.Add(p => p.ShowCalendarWeek, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-calendar-week-number", component.Markup);
|
||||
Assert.Equal(8, component.FindAll(".rz-calendar-view th").Count());
|
||||
// check header and week number column
|
||||
Assert.Single(component.FindAll("th.rz-datepicker-week-number"));
|
||||
Assert.Equal(6, component.FindAll("td.rz-calendar-week-number").Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_ShowCalendarWeekFalse_NoAdditionalColumn()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
|
||||
{
|
||||
parameter.Add(p => p.ShowCalendarWeek, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-calendar-week-number", component.Markup);
|
||||
Assert.Equal(7, component.FindAll(".rz-calendar-view th").Count());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_ShowCalendarWeekWithCustomTitle_TitleCorrectlyRendered()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<DateTime>>(parameter =>
|
||||
{
|
||||
parameter.Add(p => p.ShowCalendarWeek, true);
|
||||
parameter.Add(p => p.CalendarWeekTitle, "Wk");
|
||||
});
|
||||
|
||||
var weekNumberHeader = component.Find(".rz-calendar-view th.rz-datepicker-week-number");
|
||||
Assert.Contains("Wk", weekNumberHeader.InnerHtml);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Multiple_Selects_IEnumerableDateTime()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
IEnumerable<DateTime> emitted = null;
|
||||
var initial = new DateTime(2024, 1, 1);
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTime>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.InitialViewDate, initial);
|
||||
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
|
||||
});
|
||||
|
||||
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "10").ParentElement.Click());
|
||||
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "12").ParentElement.Click());
|
||||
|
||||
Assert.NotNull(emitted);
|
||||
var list = emitted.ToList();
|
||||
Assert.Equal(2, list.Count);
|
||||
Assert.Contains(new DateTime(2024, 1, 10), list.Select(d => d.Date));
|
||||
Assert.Contains(new DateTime(2024, 1, 12), list.Select(d => d.Date));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Multiple_Selects_IEnumerableNullableDateTime()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
IEnumerable<DateTime?> emitted = null;
|
||||
var initial = new DateTime(2024, 2, 1);
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTime?>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.InitialViewDate, initial);
|
||||
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
|
||||
});
|
||||
|
||||
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "3").ParentElement.Click());
|
||||
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "14").ParentElement.Click());
|
||||
|
||||
Assert.NotNull(emitted);
|
||||
var list = emitted.ToList();
|
||||
Assert.Equal(2, list.Count);
|
||||
Assert.Contains(new DateTime(2024, 2, 3), list.Select(d => d.Value.Date));
|
||||
Assert.Contains(new DateTime(2024, 2, 14), list.Select(d => d.Value.Date));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Multiple_Emits_IEnumerableDateTimeOffsetNullable_WithUtcKind()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
IEnumerable<DateTimeOffset?> emitted = null;
|
||||
var initial = new DateTime(2024, 3, 1);
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateTimeOffset?>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.InitialViewDate, initial);
|
||||
parameters.Add(p => p.Kind, DateTimeKind.Utc);
|
||||
parameters.Add(p => p.ValueChanged, args => { emitted = args; });
|
||||
});
|
||||
|
||||
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "5").ParentElement.Click());
|
||||
component.InvokeAsync(() => component.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "20").ParentElement.Click());
|
||||
|
||||
Assert.NotNull(emitted);
|
||||
var list = emitted.ToList();
|
||||
Assert.Equal(2, list.Count);
|
||||
Assert.All(list, dto => Assert.Equal(TimeSpan.Zero, dto.Value.Offset));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DatePicker_Multiple_Emits_IEnumerableDateOnlyAndTimeOnlyNullable()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
IEnumerable<DateOnly?> emittedDates = null;
|
||||
IEnumerable<TimeOnly?> emittedTimes = null;
|
||||
var initial = new DateTime(2024, 4, 1);
|
||||
|
||||
var compDates = ctx.RenderComponent<RadzenDatePicker<IEnumerable<DateOnly?>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.InitialViewDate, initial);
|
||||
parameters.Add(p => p.ValueChanged, args => { emittedDates = args; });
|
||||
});
|
||||
|
||||
compDates.InvokeAsync(() => compDates.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "7").ParentElement.Click());
|
||||
compDates.InvokeAsync(() => compDates.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "9").ParentElement.Click());
|
||||
|
||||
Assert.NotNull(emittedDates);
|
||||
var dateList = emittedDates.ToList();
|
||||
Assert.Equal(2, dateList.Count);
|
||||
Assert.Contains(new DateOnly(2024, 4, 7), dateList.Select(d => d.Value));
|
||||
Assert.Contains(new DateOnly(2024, 4, 9), dateList.Select(d => d.Value));
|
||||
|
||||
// TimeOnly? emission should produce midnight times for selected dates
|
||||
var compTimes = ctx.RenderComponent<RadzenDatePicker<IEnumerable<TimeOnly?>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.InitialViewDate, initial);
|
||||
parameters.Add(p => p.ValueChanged, args => { emittedTimes = args; });
|
||||
});
|
||||
|
||||
compTimes.InvokeAsync(() => compTimes.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "1").ParentElement.Click());
|
||||
compTimes.InvokeAsync(() => compTimes.FindAll("td:not(.rz-calendar-other-month) span").First(e => e.TextContent == "2").ParentElement.Click());
|
||||
|
||||
Assert.NotNull(emittedTimes);
|
||||
var timeList = emittedTimes.ToList();
|
||||
Assert.Equal(2, timeList.Count);
|
||||
Assert.All(timeList, t => Assert.Equal(new TimeOnly(0, 0, 0), t.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
413
Radzen.Blazor.Tests/DialogServiceTests.cs
Normal file
413
Radzen.Blazor.Tests/DialogServiceTests.cs
Normal file
@@ -0,0 +1,413 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class DialogServiceTests : ComponentBase
|
||||
{
|
||||
public class OpenDialogTests
|
||||
{
|
||||
[Fact(DisplayName = "DialogOptions default values are set correctly")]
|
||||
public void DialogOptions_DefaultValues_AreSetCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var options = new DialogOptions();
|
||||
var dialogService = new DialogService(null, null);
|
||||
|
||||
// Act
|
||||
dialogService.OpenDialog<DialogServiceTests>("Test", [], options);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("600px", options.Width);
|
||||
Assert.Equal("", options.Left);
|
||||
Assert.Equal("", options.Top);
|
||||
Assert.Equal("", options.Bottom);
|
||||
Assert.Equal("", options.Height);
|
||||
Assert.Equal("", options.Style);
|
||||
Assert.Equal("", options.CssClass);
|
||||
Assert.Equal("", options.WrapperCssClass);
|
||||
Assert.Equal("", options.ContentCssClass);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "DialogOptions values are retained after OpenDialog call")]
|
||||
public void DialogOptions_Values_AreRetained_AfterOpenDialogCall()
|
||||
{
|
||||
// Arrange
|
||||
var options = new DialogOptions
|
||||
{
|
||||
Width = "800px",
|
||||
Left = "10px",
|
||||
Top = "20px",
|
||||
Bottom = "30px",
|
||||
Height = "400px",
|
||||
Style = "background-color: red;",
|
||||
CssClass = "custom-class",
|
||||
WrapperCssClass = "wrapper-class",
|
||||
ContentCssClass = "content-class"
|
||||
};
|
||||
var dialogService = new DialogService(null, null);
|
||||
|
||||
// Act
|
||||
dialogService.OpenDialog<DialogServiceTests>("Test", [], options);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("800px", options.Width);
|
||||
Assert.Equal("10px", options.Left);
|
||||
Assert.Equal("20px", options.Top);
|
||||
Assert.Equal("30px", options.Bottom);
|
||||
Assert.Equal("400px", options.Height);
|
||||
Assert.Equal("background-color: red;", options.Style);
|
||||
Assert.Equal("custom-class", options.CssClass);
|
||||
Assert.Equal("wrapper-class", options.WrapperCssClass);
|
||||
Assert.Equal("content-class", options.ContentCssClass);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "DialogOptions is null and default values are set correctly")]
|
||||
public void DialogOptions_IsNull_DefaultValues_AreSetCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
DialogOptions resultingOptions = null;
|
||||
var dialogService = new DialogService(null, null);
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options;
|
||||
|
||||
// Act
|
||||
dialogService.OpenDialog<DialogServiceTests>("Test", [], null);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("600px", resultingOptions.Width);
|
||||
Assert.Equal("", resultingOptions.Left);
|
||||
Assert.Equal("", resultingOptions.Top);
|
||||
Assert.Equal("", resultingOptions.Bottom);
|
||||
Assert.Equal("", resultingOptions.Height);
|
||||
Assert.Equal("", resultingOptions.Style);
|
||||
Assert.Equal("", resultingOptions.CssClass);
|
||||
Assert.Equal("", resultingOptions.WrapperCssClass);
|
||||
Assert.Equal("", resultingOptions.ContentCssClass);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Open with dynamic component type reflective calls are resolved without exception")]
|
||||
public void Open_DynamicComponentType_Reflective_Calls_Resolve()
|
||||
{
|
||||
// Arrange
|
||||
string resultingTitle = null;
|
||||
Type resultingType = null;
|
||||
var dialogService = new DialogService(null, null);
|
||||
dialogService.OnOpen += (title, type, _, _) =>
|
||||
{
|
||||
resultingTitle = title;
|
||||
resultingType = type;
|
||||
};
|
||||
|
||||
dialogService.Open("Dynamic Open", typeof(RadzenButton), []);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Dynamic Open", resultingTitle);
|
||||
Assert.Equal(typeof(RadzenButton), resultingType);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "OpenAsync with dynamic component type reflective calls are resolved without exception")]
|
||||
public async Task OpenAsync_DynamicComponentType_Reflective_Calls_Resolve()
|
||||
{
|
||||
// Arrange
|
||||
string resultingTitle = null;
|
||||
Type resultingType = null;
|
||||
var dialogService = new DialogService(null, null);
|
||||
dialogService.OnOpen += (title, type, _, _) =>
|
||||
{
|
||||
resultingTitle = title;
|
||||
resultingType = type;
|
||||
};
|
||||
|
||||
var openTask = dialogService.OpenAsync("Dynamic Open", typeof(RadzenButton), []);
|
||||
dialogService.Close();
|
||||
await openTask;
|
||||
|
||||
// Assert
|
||||
Assert.Equal("Dynamic Open", resultingTitle);
|
||||
Assert.Equal(typeof(RadzenButton), resultingType);
|
||||
}
|
||||
}
|
||||
|
||||
public class OpenSideDialogTests
|
||||
{
|
||||
[Fact(DisplayName = "SideDialogOptions resizable option is retained after OpenSideDialog call")]
|
||||
public void SideDialogOptions_Resizable_AreRetained_AfterOpenSideDialogCall()
|
||||
{
|
||||
// Arrange
|
||||
var options = new SideDialogOptions { Resizable = true };
|
||||
SideDialogOptions resultingOptions = null;
|
||||
var dialogService = new DialogService(null, null);
|
||||
dialogService.OnSideOpen += (_, _, sideOptions) => resultingOptions = sideOptions;
|
||||
|
||||
// Act
|
||||
dialogService.OpenSide<DialogServiceTests>("Test", [], options);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Same(options, resultingOptions);
|
||||
Assert.True(resultingOptions.Resizable);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Side dialog shows resize bar when Resizable is true")]
|
||||
public void SideDialog_Resizable_ShowsResizeBar()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
|
||||
// Render the dialog host
|
||||
var cut = ctx.RenderComponent<RadzenDialog>();
|
||||
|
||||
// Open a side dialog with Resizable=true
|
||||
var dialogService = ctx.Services.GetRequiredService<DialogService>();
|
||||
cut.InvokeAsync(() => dialogService.OpenSide("Test", typeof(RadzenButton),
|
||||
new Dictionary<string, object>(), new SideDialogOptions { Resizable = true }));
|
||||
|
||||
// Assert: the resize bar element is present
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
var markup = cut.Markup;
|
||||
Assert.Contains("rz-dialog-resize-bar", markup);
|
||||
// Optionally ensure the inner handle exists too
|
||||
Assert.Contains("rz-resize", markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "Side dialog hides resize bar when Resizable is false")]
|
||||
public void SideDialog_NonResizable_HidesResizeBar()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
|
||||
// Render the dialog host
|
||||
var cut = ctx.RenderComponent<RadzenDialog>();
|
||||
|
||||
// Open a side dialog with Resizable=false
|
||||
var dialogService = ctx.Services.GetRequiredService<DialogService>();
|
||||
cut.InvokeAsync(() => dialogService.OpenSide("Test", typeof(RadzenButton),
|
||||
new Dictionary<string, object>(), new SideDialogOptions()));
|
||||
|
||||
// Assert: the resize bar element is not present
|
||||
cut.WaitForAssertion(() =>
|
||||
{
|
||||
var markup = cut.Markup;
|
||||
Assert.DoesNotContain("rz-dialog-resize-bar", markup);
|
||||
});
|
||||
}
|
||||
}
|
||||
public class ConfirmTests
|
||||
{
|
||||
[Fact(DisplayName = "ConfirmOptions is null and default values are set correctly")]
|
||||
public async Task ConfirmOptions_IsNull_AreSetCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var dialogService = new DialogService(null, null);
|
||||
ConfirmOptions resultingOptions = null;
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as ConfirmOptions;
|
||||
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource.Cancel();
|
||||
|
||||
// Act
|
||||
try
|
||||
{
|
||||
await dialogService.Confirm(cancellationToken: cancellationTokenSource.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// this is expected
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("Ok", resultingOptions.OkButtonText);
|
||||
Assert.Equal("Cancel", resultingOptions.CancelButtonText);
|
||||
Assert.Equal("600px", resultingOptions.Width);
|
||||
Assert.Equal("", resultingOptions.Style);
|
||||
Assert.Equal("rz-dialog-confirm", resultingOptions.CssClass);
|
||||
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "ConfirmOptions default values are set correctly")]
|
||||
public async Task ConfirmOptions_DefaultValues_AreSetCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var dialogService = new DialogService(null, null);
|
||||
ConfirmOptions resultingOptions = null;
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as ConfirmOptions;
|
||||
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource.Cancel();
|
||||
|
||||
// Act
|
||||
try
|
||||
{
|
||||
await dialogService.Confirm(options: new(), cancellationToken: cancellationTokenSource.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// this is expected
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("Ok", resultingOptions.OkButtonText);
|
||||
Assert.Equal("Cancel", resultingOptions.CancelButtonText);
|
||||
Assert.Equal("600px", resultingOptions.Width);
|
||||
Assert.Equal("", resultingOptions.Style);
|
||||
Assert.Equal("rz-dialog-confirm", resultingOptions.CssClass);
|
||||
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
|
||||
}
|
||||
[Fact(DisplayName = "ConfirmOptions values are retained after Confirm call")]
|
||||
public async Task Confirm_ProvidedValues_AreRetained()
|
||||
{
|
||||
// Arrange
|
||||
var dialogService = new DialogService(null, null);
|
||||
var options = new ConfirmOptions
|
||||
{
|
||||
OkButtonText = "XXX",
|
||||
CancelButtonText = "YYY",
|
||||
Width = "800px",
|
||||
Style = "background-color: red;",
|
||||
CssClass = "custom-class",
|
||||
WrapperCssClass = "wrapper-class"
|
||||
};
|
||||
ConfirmOptions resultingOptions = null;
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as ConfirmOptions;
|
||||
|
||||
// We break out of the dialog immediately, but the options should still be set
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource.Cancel();
|
||||
|
||||
// Act
|
||||
try
|
||||
{
|
||||
await dialogService.Confirm("Confirm?", "Confirm", options, cancellationToken: cancellationTokenSource.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// this is expected
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("XXX", resultingOptions.OkButtonText);
|
||||
Assert.Equal("YYY", resultingOptions.CancelButtonText);
|
||||
Assert.Equal("800px", resultingOptions.Width);
|
||||
Assert.Equal("background-color: red;", resultingOptions.Style);
|
||||
Assert.Equal("rz-dialog-confirm custom-class", resultingOptions.CssClass);
|
||||
Assert.Equal("rz-dialog-wrapper wrapper-class", resultingOptions.WrapperCssClass);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class AlertTests
|
||||
{
|
||||
[Fact(DisplayName = "AlertOptions is null and default values are set correctly")]
|
||||
public async Task AlertOptions_IsNull_AreSetCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var dialogService = new DialogService(null, null);
|
||||
AlertOptions resultingOptions = null;
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as AlertOptions;
|
||||
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource.Cancel();
|
||||
|
||||
// Act
|
||||
try
|
||||
{
|
||||
await dialogService.Alert(cancellationToken: cancellationTokenSource.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// this is expected
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("Ok", resultingOptions.OkButtonText);
|
||||
Assert.Equal("600px", resultingOptions.Width);
|
||||
Assert.Equal("", resultingOptions.Style);
|
||||
Assert.Equal("rz-dialog-alert", resultingOptions.CssClass);
|
||||
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
|
||||
}
|
||||
|
||||
[Fact(DisplayName = "AlertOptions default values are set correctly")]
|
||||
public async Task AlertOptions_DefaultValues_AreSetCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var dialogService = new DialogService(null, null);
|
||||
AlertOptions resultingOptions = null;
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as AlertOptions;
|
||||
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource.Cancel();
|
||||
|
||||
// Act
|
||||
try
|
||||
{
|
||||
await dialogService.Alert(options: new(), cancellationToken: cancellationTokenSource.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// this is expected
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("Ok", resultingOptions.OkButtonText);
|
||||
Assert.Equal("600px", resultingOptions.Width);
|
||||
Assert.Equal("", resultingOptions.Style);
|
||||
Assert.Equal("rz-dialog-alert", resultingOptions.CssClass);
|
||||
Assert.Equal("rz-dialog-wrapper", resultingOptions.WrapperCssClass);
|
||||
}
|
||||
[Fact(DisplayName = "AlertOptions values are retained after Alert call")]
|
||||
public async Task Alert_ProvidedValues_AreRetained()
|
||||
{
|
||||
// Arrange
|
||||
var dialogService = new DialogService(null, null);
|
||||
var options = new AlertOptions
|
||||
{
|
||||
OkButtonText = "XXX",
|
||||
Width = "800px",
|
||||
Style = "background-color: red;",
|
||||
CssClass = "custom-class",
|
||||
WrapperCssClass = "wrapper-class"
|
||||
};
|
||||
AlertOptions resultingOptions = null;
|
||||
dialogService.OnOpen += (title, type, parameters, options) => resultingOptions = options as AlertOptions;
|
||||
|
||||
// We break out of the dialog immediately, but the options should still be set
|
||||
using var cancellationTokenSource = new CancellationTokenSource();
|
||||
cancellationTokenSource.Cancel();
|
||||
|
||||
// Act
|
||||
try
|
||||
{
|
||||
await dialogService.Alert("Alert?", "Alert", options, cancellationToken: cancellationTokenSource.Token);
|
||||
}
|
||||
catch (TaskCanceledException)
|
||||
{
|
||||
// this is expected
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(resultingOptions);
|
||||
Assert.Equal("XXX", resultingOptions.OkButtonText);
|
||||
Assert.Equal("800px", resultingOptions.Width);
|
||||
Assert.Equal("background-color: red;", resultingOptions.Style);
|
||||
Assert.Equal("rz-dialog-alert custom-class", resultingOptions.CssClass);
|
||||
Assert.Equal("rz-dialog-wrapper wrapper-class", resultingOptions.WrapperCssClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
Radzen.Blazor.Tests/Dollars.cs
Normal file
58
Radzen.Blazor.Tests/Dollars.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Radzen.Blazor.Tests;
|
||||
|
||||
[TypeConverter(typeof(DollarsTypeConverter))]
|
||||
public readonly record struct Dollars(decimal Amount) : IComparable<decimal>
|
||||
{
|
||||
public int CompareTo(decimal other)
|
||||
{
|
||||
return Amount.CompareTo(other);
|
||||
}
|
||||
|
||||
public string ToString(string format, CultureInfo culture = null) => Amount.ToString(format, culture ?? CultureInfo.CreateSpecificCulture("en-US"));
|
||||
public override string ToString() => Amount.ToString("F2", CultureInfo.CreateSpecificCulture("en-US"));
|
||||
}
|
||||
|
||||
public class DollarsTypeConverter : TypeConverter
|
||||
{
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == typeof(decimal) ||
|
||||
sourceType == typeof(string))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(decimal))
|
||||
return true;
|
||||
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
if (value is decimal d)
|
||||
return new Dollars(d);
|
||||
|
||||
if (value is string s)
|
||||
return decimal.TryParse(s, culture, out var val) ? new Dollars(val) : null;
|
||||
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
if (destinationType == typeof(decimal) && value is Dollars d)
|
||||
return d.Amount;
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
289
Radzen.Blazor.Tests/DropDownDataGridTests.cs
Normal file
289
Radzen.Blazor.Tests/DropDownDataGridTests.cs
Normal file
@@ -0,0 +1,289 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class DropDownDataGridTests
|
||||
{
|
||||
class Customer
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string CompanyName { get; set; }
|
||||
public string ContactName { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>();
|
||||
|
||||
Assert.Contains(@"rz-dropdown", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_DropdownTrigger()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>();
|
||||
|
||||
Assert.Contains("rz-dropdown-trigger", component.Markup);
|
||||
Assert.Contains("rzi-chevron-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_WithData()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1", "Item2", "Item3" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-lookup-panel", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_WithCustomTextValueProperties()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<Customer>
|
||||
{
|
||||
new Customer { Id = 1, CompanyName = "Acme Corp", ContactName = "John Doe" },
|
||||
new Customer { Id = 2, CompanyName = "Tech Inc", ContactName = "Jane Smith" }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, "CompanyName");
|
||||
parameters.Add(p => p.ValueProperty, "Id");
|
||||
});
|
||||
|
||||
Assert.Contains("rz-lookup-panel", component.Markup);
|
||||
Assert.Contains("rz-data-grid", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_DataGrid()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
// DropDownDataGrid embeds a DataGrid
|
||||
Assert.Contains("rz-data-grid", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_AllowFiltering()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1", "Item2" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-lookup-search", component.Markup);
|
||||
Assert.Contains("rz-lookup-search-input", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_Placeholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Placeholder, "Select an item");
|
||||
});
|
||||
|
||||
Assert.Contains("Select an item", component.Markup);
|
||||
Assert.Contains("rz-placeholder", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_AllowClear_WithValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowClear, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.Value, "Item1");
|
||||
});
|
||||
|
||||
Assert.Contains("rz-dropdown-clear-icon", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_DoesNotRender_AllowClear_WhenNotAllowed()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowClear, false);
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.Value, "Item1");
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-dropdown-clear-icon", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_Multiple_Panel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<IEnumerable<int>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-multiselect-panel", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_Multiple_WithChips()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1", "Item2" };
|
||||
var selectedItems = new List<string> { "Item1" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<IEnumerable<string>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Chips, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.Value, selectedItems);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-dropdown-chips-wrapper", component.Markup);
|
||||
Assert.Contains("rz-chip", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_AllowSorting()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<Customer>
|
||||
{
|
||||
new Customer { Id = 1, CompanyName = "Acme" }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowSorting, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, "CompanyName");
|
||||
});
|
||||
|
||||
Assert.Contains("rz-data-grid", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_SearchTextPlaceholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
parameters.Add(p => p.SearchTextPlaceholder, "Type to filter...");
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("placeholder=\"Type to filter...\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_EmptyText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, new List<string>());
|
||||
parameters.Add(p => p.EmptyText, "No items found");
|
||||
});
|
||||
|
||||
Assert.Contains("No items found", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_PageSize()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = Enumerable.Range(1, 20).Select(i => $"Item {i}").ToList();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.PageSize, 10);
|
||||
});
|
||||
|
||||
// DataGrid with paging should be present
|
||||
Assert.Contains("rz-data-grid", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDownDataGrid_Renders_AllowRowSelectOnRowClick()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1", "Item2" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDownDataGrid<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowRowSelectOnRowClick, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-data-grid", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
743
Radzen.Blazor.Tests/DropDownTests.cs
Normal file
743
Radzen.Blazor.Tests/DropDownTests.cs
Normal file
@@ -0,0 +1,743 @@
|
||||
using AngleSharp.Dom;
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class DropDownTests
|
||||
{
|
||||
class DataItem
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public int Id { get; set; }
|
||||
public bool Disabled { get; set; }
|
||||
}
|
||||
|
||||
private static IRenderedComponent<RadzenDropDown<T>> DropDown<T>(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenDropDown<T>>> configure = null)
|
||||
{
|
||||
var data = new[] {
|
||||
new DataItem { Text = "Item 1", Id = 1 },
|
||||
new DataItem { Text = "Item 2", Id = 2 },
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDown<T>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
|
||||
|
||||
if (configure != null)
|
||||
{
|
||||
configure.Invoke(parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
}
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task Dropdown_SelectItem_Method_Should_Not_Throw()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<int>(ctx);
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Equal(2, items.Count);
|
||||
|
||||
//this throws
|
||||
await component.InvokeAsync(async () => await component.Instance.SelectItem(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_RendersItems()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<int>(ctx);
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Equal(2, items.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesSelectionStyleForIntValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<int>(ctx);
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
items[0].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Contains("rz-state-highlight", items[0].ClassList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesSelectionStyleForStringValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<string>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Text));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
items[0].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
items = component.FindAll(".rz-dropdown-item");
|
||||
|
||||
Assert.Contains("rz-state-highlight", items[0].ClassList);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_Respects_ItemEqualityComparer()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
List<DataItem> boundCollection = [new() { Text = "Item 2" }];
|
||||
|
||||
var component = DropDown<List<DataItem>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ItemComparer, new DataItemComparer());
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, boundCollection);
|
||||
});
|
||||
|
||||
var selectedItems = component.FindAll(".rz-state-highlight");
|
||||
Assert.Equal(1, selectedItems.Count);
|
||||
Assert.Equal("Item 2", selectedItems[0].TextContent.Trim());
|
||||
|
||||
// select Item 1 in list
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
|
||||
selectedItems = component.FindAll(".rz-state-highlight");
|
||||
Assert.Equal(2, selectedItems.Count);
|
||||
Assert.Equal("Item 1", selectedItems[0].TextContent.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesSelectionStyleWhenMultipleSelectionIsEnabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = DropDown<string>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Text));
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[0].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[1].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var selectedItems = component.FindAll(".rz-state-highlight");
|
||||
|
||||
Assert.Equal(2, selectedItems.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesValueTemplateOnMultipleSelection()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var valueTemplateFragment = (RenderFragment<dynamic>)(_context =>
|
||||
builder =>
|
||||
{
|
||||
builder.AddContent(0, $"value: {_context.Text}");
|
||||
});
|
||||
|
||||
var component = DropDown<string>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true)
|
||||
.Add(p => p.ValueTemplate, valueTemplateFragment);
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[0].Click();
|
||||
items[1].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var selectedItems = component.Find(".rz-inputtext");
|
||||
|
||||
Assert.Contains("value: Item 1,value: Item 2", selectedItems.Text());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesValueTemplateWhenTepmlateDefined()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var valueTemplateFragment = (RenderFragment<dynamic>)(_context =>
|
||||
builder =>
|
||||
{
|
||||
builder.AddContent(0, $"value: {_context.Text}");
|
||||
});
|
||||
|
||||
var templateFragment = (RenderFragment<dynamic>)(_context =>
|
||||
builder =>
|
||||
{
|
||||
builder.AddContent(0, $"template: {_context.Text}");
|
||||
});
|
||||
|
||||
var component = DropDown<string>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true)
|
||||
.Add(p => p.ValueTemplate, valueTemplateFragment)
|
||||
.Add(p => p.Template, templateFragment);
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[0].Click();
|
||||
items[1].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var selectedItems = component.Find(".rz-inputtext");
|
||||
var itemsText = component.FindAll(".rz-multiselect-item-content");
|
||||
|
||||
Assert.Collection(itemsText, item => Assert.Contains("template: Item 1", item.Text()), item => Assert.Contains("template: Item 2", item.Text()));
|
||||
Assert.Contains("value: Item 1,value: Item 2", selectedItems.Text());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_AppliesValueTemplateOnMultipleSelectionChips()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var valueTemplateFragment = (RenderFragment<dynamic>)(_context =>
|
||||
builder =>
|
||||
{
|
||||
builder.AddContent(0, $"value: {_context.Text}");
|
||||
});
|
||||
|
||||
var component = DropDown<string>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true)
|
||||
.Add(p => p.ValueTemplate, valueTemplateFragment)
|
||||
.Add(p => p.Chips, true);
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
items[0].Click();
|
||||
items[1].Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var selectedItems = component.FindAll(".rz-chip-text");
|
||||
|
||||
Assert.Collection(selectedItems, item => Assert.Contains("value: Item 1", item.Text()), item => Assert.Contains("value: Item 2", item.Text()));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, true, false, true, "false")]
|
||||
[InlineData(true, false, true, false, "true")]
|
||||
[InlineData(true, false, false, false, "false")]
|
||||
[InlineData(true, false, false, true, "true")]
|
||||
[InlineData(false, false, false, true, "false")]
|
||||
public void DropDown_AllSelectedFalseIfListIsAllDisabled(bool item1Selected, bool item1Disabled, bool item2Selected, bool item2Disabled, string expectedAriaCheckedValue)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var data = new[] {
|
||||
new DataItem { Text = "Item 1", Id = 1, Disabled = item1Disabled },
|
||||
new DataItem { Text = "Item 2", Id = 2, Disabled = item2Disabled },
|
||||
};
|
||||
|
||||
List<int> selectedValues = [];
|
||||
if (item1Selected)
|
||||
{
|
||||
selectedValues.Add(data[0].Id);
|
||||
}
|
||||
if (item2Selected)
|
||||
{
|
||||
selectedValues.Add(data[1].Id);
|
||||
}
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDown<List<int>>>(parameters => parameters
|
||||
.Add(p => p.Data, data)
|
||||
.Add(p => p.Value, selectedValues)
|
||||
.Add(p => p.Multiple, true)
|
||||
.Add(p => p.AllowSelectAll, true)
|
||||
.Add(p => p.TextProperty, nameof(DataItem.Text))
|
||||
.Add(p => p.DisabledProperty, nameof(DataItem.Disabled))
|
||||
.Add(p => p.ValueProperty, nameof(DataItem.Id)));
|
||||
|
||||
Assert.NotNull(component);
|
||||
var highlightedItems = component.FindAll(".rz-state-highlight");
|
||||
Assert.Equal(selectedValues.Count, highlightedItems.Count);
|
||||
|
||||
|
||||
var selectAllCheckBox = component.Find(".rz-multiselect-header input[type='checkbox']");
|
||||
|
||||
Assert.Equal(expectedAriaCheckedValue, selectAllCheckBox.GetAttribute("aria-checked"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_ReferenceGenericCollectionAssignment_HashSet_ReferencesInstance()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalHashSet = new HashSet<int>();
|
||||
var capturedValue = (HashSet<int>)null;
|
||||
|
||||
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalHashSet);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValue = value));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
// Select first item
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
|
||||
// Verify the same HashSet instance is Referenced
|
||||
Assert.Same(originalHashSet, capturedValue);
|
||||
|
||||
// Verify the item was added correctly
|
||||
Assert.Single(originalHashSet);
|
||||
Assert.Contains(1, originalHashSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_ReferenceGenericCollectionAssignment_HashSet_MultipleSelections()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalHashSet = new HashSet<int> { 2 }; // Pre-populate with Item 2
|
||||
var capturedValues = new List<HashSet<int>>();
|
||||
|
||||
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalHashSet);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValues.Add(value)));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
// Select first item (should add to existing collection)
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
|
||||
// Verify the same HashSet instance is Referenced
|
||||
Assert.Single(capturedValues);
|
||||
Assert.Same(originalHashSet, capturedValues[0]);
|
||||
|
||||
// Verify both items are now in the collection
|
||||
Assert.Equal(2, originalHashSet.Count);
|
||||
Assert.Contains(1, originalHashSet);
|
||||
Assert.Contains(2, originalHashSet);
|
||||
|
||||
// Deselect second item (should remove from collection)
|
||||
items = component.FindAll(".rz-multiselect-item"); // Re-find items after render
|
||||
items[1].Click();
|
||||
component.Render();
|
||||
|
||||
// Verify the same HashSet instance is still Referenced
|
||||
Assert.Equal(2, capturedValues.Count);
|
||||
Assert.Same(originalHashSet, capturedValues[1]);
|
||||
|
||||
// Verify only first item remains
|
||||
Assert.Single(originalHashSet);
|
||||
Assert.Contains(1, originalHashSet);
|
||||
Assert.DoesNotContain(2, originalHashSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_ReferenceGenericCollectionAssignment_SortedSet_ReferencesInstance()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalSortedSet = new SortedSet<int>();
|
||||
var capturedValue = (SortedSet<int>)null;
|
||||
|
||||
var component = DropDownWithReferenceCollection<SortedSet<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalSortedSet);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<SortedSet<int>>(this, value => capturedValue = value));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
// Select both items
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
items = component.FindAll(".rz-multiselect-item"); // Re-find items after first click
|
||||
items[1].Click();
|
||||
component.Render();
|
||||
|
||||
// Verify the same SortedSet instance is Referenced
|
||||
Assert.Same(originalSortedSet, capturedValue);
|
||||
|
||||
// Verify items are sorted correctly
|
||||
Assert.Equal(2, originalSortedSet.Count);
|
||||
var sortedItems = originalSortedSet.ToList();
|
||||
Assert.Equal(1, sortedItems[0]);
|
||||
Assert.Equal(2, sortedItems[1]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_ReferenceGenericCollectionAssignment_CustomCollection_ReferencesInstance()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalCollection = new CustomCollection<int>();
|
||||
var capturedValue = (CustomCollection<int>)null;
|
||||
|
||||
var component = DropDownWithReferenceCollection<CustomCollection<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalCollection);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<CustomCollection<int>>(this, value => capturedValue = value));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
// Select first item
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
|
||||
// Verify the same custom collection instance is Referenced
|
||||
Assert.Same(originalCollection, capturedValue);
|
||||
|
||||
// Verify the item was added correctly
|
||||
Assert.Single(originalCollection);
|
||||
Assert.Contains(1, originalCollection);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void DropDown_ReferenceGenericCollectionAssignment_List_ReferencesInstance()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalList = new List<int>();
|
||||
var capturedValue = (List<int>)null;
|
||||
|
||||
var component = DropDownWithReferenceCollection<List<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalList);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<List<int>>(this, value => capturedValue = value));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
// Select first item
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
|
||||
// For List<T>, it should now Reference the instance since we removed the IList exclusion
|
||||
// Arrays are now excluded instead
|
||||
Assert.Same(originalList, capturedValue);
|
||||
|
||||
// And the content should be correct
|
||||
Assert.Single(capturedValue);
|
||||
Assert.Contains(1, capturedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_ReferenceGenericCollectionAssignment_DisabledByDefault()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalList = new List<int>();
|
||||
var capturedValue = (List<int>)null;
|
||||
|
||||
var component = DropDown<List<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalList);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<List<int>>(this, value => capturedValue = value));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
var items = component.FindAll(".rz-multiselect-item");
|
||||
|
||||
// Select first item
|
||||
items[0].Click();
|
||||
component.Render();
|
||||
|
||||
// When ReferenceCollectionOnSelection is false (default), a new instance should be created
|
||||
Assert.NotSame(originalList, capturedValue);
|
||||
|
||||
// But the content should still be correct
|
||||
Assert.Single(capturedValue);
|
||||
Assert.Contains(1, capturedValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_Reset_PreservesCollectionInstanceButClears()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalHashSet = new HashSet<int> { 1, 2 }; // Pre-populate
|
||||
var capturedValues = new List<HashSet<int>>();
|
||||
|
||||
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Value, originalHashSet);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValues.Add(value)));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
// Verify initial state - collection should have 2 items
|
||||
Assert.Equal(2, originalHashSet.Count);
|
||||
Assert.Contains(1, originalHashSet);
|
||||
Assert.Contains(2, originalHashSet);
|
||||
|
||||
// Call Reset (public method that calls ClearAll internally)
|
||||
component.InvokeAsync(() => component.Instance.Reset());
|
||||
component.Render();
|
||||
|
||||
// Verify the same HashSet instance is preserved
|
||||
Assert.Single(capturedValues);
|
||||
Assert.Same(originalHashSet, capturedValues[0]);
|
||||
|
||||
// Verify the collection is now cleared
|
||||
Assert.Empty(originalHashSet);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_SelectAll_PreservesCollectionInstanceAndPopulates()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var originalHashSet = new HashSet<int>(); // Start empty
|
||||
var capturedValues = new List<HashSet<int>>();
|
||||
|
||||
var component = DropDownWithReferenceCollection<HashSet<int>>(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.AllowSelectAll, true);
|
||||
parameters.Add(p => p.Value, originalHashSet);
|
||||
parameters.Add(p => p.ValueChanged, EventCallback.Factory.Create<HashSet<int>>(this, value => capturedValues.Add(value)));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
});
|
||||
|
||||
// Verify initial state - collection should be empty
|
||||
Assert.Empty(originalHashSet);
|
||||
|
||||
// Find and click the "Select All" checkbox
|
||||
var selectAllCheckBox = component.Find(".rz-multiselect-header input[type='checkbox']");
|
||||
selectAllCheckBox.Click();
|
||||
component.Render();
|
||||
|
||||
// Verify the same HashSet instance is preserved
|
||||
Assert.Single(capturedValues);
|
||||
Assert.Same(originalHashSet, capturedValues[0]);
|
||||
|
||||
// Verify the collection now contains both items
|
||||
Assert.Equal(2, originalHashSet.Count);
|
||||
Assert.Contains(1, originalHashSet);
|
||||
Assert.Contains(2, originalHashSet);
|
||||
}
|
||||
|
||||
class ReferenceCollectionDropDown<T> : Radzen.Blazor.RadzenDropDown<T>
|
||||
{
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
PreserveCollectionOnSelection = true;
|
||||
base.OnInitialized();
|
||||
}
|
||||
}
|
||||
|
||||
private static IRenderedComponent<ReferenceCollectionDropDown<T>> DropDownWithReferenceCollection<T>(TestContext ctx, Action<ComponentParameterCollectionBuilder<ReferenceCollectionDropDown<T>>> configure = null)
|
||||
{
|
||||
var data = new[] {
|
||||
new DataItem { Text = "Item 1", Id = 1 },
|
||||
new DataItem { Text = "Item 2", Id = 2 },
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<ReferenceCollectionDropDown<T>>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
|
||||
|
||||
if (configure != null)
|
||||
{
|
||||
configure.Invoke(parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
}
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
class DataItemComparer : IEqualityComparer<DataItem>, IEqualityComparer<object>
|
||||
{
|
||||
public bool Equals(DataItem x, DataItem y)
|
||||
{
|
||||
if (ReferenceEquals(x, y)) return true;
|
||||
if (x is null) return false;
|
||||
if (y is null) return false;
|
||||
if (x.GetType() != y.GetType()) return false;
|
||||
return x.Text == y.Text;
|
||||
}
|
||||
|
||||
public int GetHashCode(DataItem obj)
|
||||
{
|
||||
return obj.Text.GetHashCode();
|
||||
}
|
||||
|
||||
public new bool Equals(object x, object y)
|
||||
{
|
||||
return Equals((DataItem)x, (DataItem)y);
|
||||
}
|
||||
|
||||
public int GetHashCode(object obj)
|
||||
{
|
||||
return GetHashCode((DataItem)obj);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class CustomCollection<T> : ICollection<T>
|
||||
{
|
||||
private readonly List<T> _items = new();
|
||||
|
||||
public int Count => _items.Count;
|
||||
public bool IsReadOnly => false;
|
||||
|
||||
public void Add(T item) => _items.Add(item);
|
||||
public void Clear() => _items.Clear();
|
||||
public bool Contains(T item) => _items.Contains(item);
|
||||
public void CopyTo(T[] array, int arrayIndex) => _items.CopyTo(array, arrayIndex);
|
||||
public bool Remove(T item) => _items.Remove(item);
|
||||
public IEnumerator<T> GetEnumerator() => _items.GetEnumerator();
|
||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_Renders_Placeholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDown<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Placeholder, "Select an option");
|
||||
});
|
||||
|
||||
Assert.Contains("Select an option", component.Markup);
|
||||
Assert.Contains("rz-placeholder", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_Renders_AllowClear_WithValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new[] { new DataItem { Text = "Item 1", Id = 1 } };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDown<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowClear, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
parameters.Add(p => p.Value, 1);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-dropdown-clear-icon", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DropDown_DoesNotRender_AllowClear_WhenNotAllowed()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new[] { new DataItem { Text = "Item 1", Id = 1 } };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenDropDown<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowClear, false);
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, nameof(DataItem.Text));
|
||||
parameters.Add(p => p.ValueProperty, nameof(DataItem.Id));
|
||||
parameters.Add(p => p.Value, 1);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-dropdown-clear-icon", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
1557
Radzen.Blazor.Tests/ExpressionParserTests.cs
Normal file
1557
Radzen.Blazor.Tests/ExpressionParserTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
323
Radzen.Blazor.Tests/ExpressionSerializerTests.cs
Normal file
323
Radzen.Blazor.Tests/ExpressionSerializerTests.cs
Normal file
@@ -0,0 +1,323 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
class TestEntity
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
public double Salary { get; set; }
|
||||
public float Score { get; set; }
|
||||
public decimal Balance { get; set; }
|
||||
public short Level { get; set; }
|
||||
public long Population { get; set; }
|
||||
public Status AccountStatus { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTimeOffset LastUpdated { get; set; }
|
||||
public Guid Id { get; set; }
|
||||
public TimeOnly StartTime { get; set; }
|
||||
public DateOnly BirthDate { get; set; }
|
||||
public List<int> Scores { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
public List<TestEntity> Children { get; set; }
|
||||
public Address Address { get; set; }
|
||||
public double[] Salaries { get; set; }
|
||||
public float[] Heights { get; set; }
|
||||
public decimal[] Balances { get; set; }
|
||||
public short[] Levels { get; set; }
|
||||
public long[] Populations { get; set; }
|
||||
public string[] Names { get; set; }
|
||||
public Guid[] Ids { get; set; }
|
||||
public DateTime[] CreatedDates { get; set; }
|
||||
public DateTimeOffset[] UpdatedDates { get; set; }
|
||||
public TimeOnly[] StartTimes { get; set; }
|
||||
public DateOnly[] BirthDates { get; set; }
|
||||
public Status[] Statuses { get; set; }
|
||||
}
|
||||
|
||||
enum Status
|
||||
{
|
||||
Active,
|
||||
Inactive,
|
||||
Suspended
|
||||
}
|
||||
|
||||
class Address
|
||||
{
|
||||
public string City { get; set; }
|
||||
public string Country { get; set; }
|
||||
}
|
||||
|
||||
public class ExpressionSerializerTests
|
||||
{
|
||||
private readonly ExpressionSerializer _serializer = new ExpressionSerializer();
|
||||
|
||||
[Fact]
|
||||
public void Serializes_SimpleBinaryExpression()
|
||||
{
|
||||
Expression<Func<int, bool>> expr = e => e > 10;
|
||||
Assert.Equal("e => (e > 10)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_StringEquality()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Name == "John";
|
||||
Assert.Equal("e => (e.Name == \"John\")", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_IntComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Age > 18;
|
||||
Assert.Equal("e => (e.Age > 18)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DoubleComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Salary < 50000.50;
|
||||
Assert.Equal("e => (e.Salary < 50000.5)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_FloatComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Score >= 85.3f;
|
||||
Assert.Equal("e => (e.Score >= 85.3)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DecimalComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Balance <= 1000.75m;
|
||||
Assert.Equal("e => (e.Balance <= 1000.75)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ShortComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Level == 3;
|
||||
Assert.Equal("e => (e.Level == 3)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_LongComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Population > 1000000L;
|
||||
Assert.Equal("e => (e.Population > 1000000)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_EnumComparison()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.AccountStatus == Status.Inactive;
|
||||
Assert.Equal("e => (e.AccountStatus == 1)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ArrayContainsValue()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Scores.Contains(100);
|
||||
Assert.Equal("e => e.Scores.Contains(100)", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ArrayNotContainsValue()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => !e.Scores.Contains(100);
|
||||
Assert.Equal("e => (!(e.Scores.Contains(100)))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ArrayInValue()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Scores.Intersect(new [] { 100 }).Any();
|
||||
Assert.Equal("e => e.Scores.Intersect(new [] { 100 }).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ArrayNotInValue()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Scores.Except(new[] { 100 }).Any();
|
||||
Assert.Equal("e => e.Scores.Except(new [] { 100 }).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { 100 }.Intersect(e.Scores).Any();
|
||||
Assert.Equal("e => new [] { 100 }.Intersect(e.Scores).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ArrayNotInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { 100 }.Except(e.Scores).Any();
|
||||
Assert.Equal("e => new [] { 100 }.Except(e.Scores).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_IntArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { 100 }.Intersect(e.Scores).Any();
|
||||
Assert.Equal("e => new [] { 100 }.Intersect(e.Scores).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_IntArrayNotInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => !new[] { 100 }.Intersect(e.Scores).Any();
|
||||
Assert.Equal("e => (!(new [] { 100 }.Intersect(e.Scores).Any()))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DoubleArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { 99.99 }.Intersect(e.Salaries).Any();
|
||||
Assert.Equal("e => new [] { 99.99 }.Intersect(e.Salaries).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_FloatArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { 5.5f }.Intersect(e.Heights).Any();
|
||||
Assert.Equal("e => new [] { 5.5 }.Intersect(e.Heights).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DecimalArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { 1000.75m }.Intersect(e.Balances).Any();
|
||||
Assert.Equal("e => new [] { 1000.75 }.Intersect(e.Balances).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ShortArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new [] { (short)3 }.Intersect(e.Levels).Any();
|
||||
Assert.Equal("e => new [] { 3 }.Intersect(e.Levels).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_LongArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new [] { 1000000L }.Intersect(e.Populations).Any();
|
||||
Assert.Equal("e => new [] { 1000000 }.Intersect(e.Populations).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_StringArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { "Alice", "Bob" }.Intersect(e.Names).Any();
|
||||
Assert.Equal("e => (new [] { \"Alice\", \"Bob\" }).Intersect(e.Names).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_GuidArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { Guid.Parse("12345678-1234-1234-1234-123456789abc") }.Intersect(e.Ids).Any();
|
||||
Assert.Equal("e => (new [] { Guid.Parse(\"12345678-1234-1234-1234-123456789abc\") }).Intersect(e.Ids).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DateTimeArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { DateTime.Parse("2023-01-01T00:00:00.000Z") }.Intersect(e.CreatedDates).Any();
|
||||
Assert.Equal("e => (new [] { DateTime.Parse(\"2023-01-01T00:00:00.000Z\") }).Intersect(e.CreatedDates).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DateTimeOffsetArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { DateTimeOffset.Parse("2023-01-01T10:30:00.000+00:00") }.Intersect(e.UpdatedDates).Any();
|
||||
Assert.Equal("e => (new [] { DateTimeOffset.Parse(\"2023-01-01T10:30:00.000+00:00\") }).Intersect(e.UpdatedDates).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DateTimeWithRoundtripKind()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e =>
|
||||
DateTime.Parse("2023-01-01T00:00:00.000Z", null, DateTimeStyles.RoundtripKind) > e.CreatedAt;
|
||||
|
||||
Assert.Equal(
|
||||
"e => (DateTime.Parse(\"2023-01-01T00:00:00.000Z\", null, (System.Globalization.DateTimeStyles)128) > e.CreatedAt)",
|
||||
_serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_TimeOnlyArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { TimeOnly.Parse("12:00:00") }.Intersect(e.StartTimes).Any();
|
||||
Assert.Equal("e => (new [] { TimeOnly.Parse(\"12:00:00\") }).Intersect(e.StartTimes).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_DateOnlyArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { DateOnly.Parse("2000-01-01") }.Intersect(e.BirthDates).Any();
|
||||
Assert.Equal("e => (new [] { DateOnly.Parse(\"2000-01-01\") }).Intersect(e.BirthDates).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_EnumArrayInValueOposite()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => new[] { Status.Active, Status.Inactive }.Intersect(e.Statuses).Any();
|
||||
Assert.Equal("e => (new [] { (Radzen.Blazor.Tests.Status)0, (Radzen.Blazor.Tests.Status)1 }).Intersect(e.Statuses).Any()", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ListContainsValue()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Tags.Contains("VIP");
|
||||
Assert.Equal("e => e.Tags.Contains(\"VIP\")", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ListNotContainsValue()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => !e.Tags.Contains("VIP");
|
||||
Assert.Equal("e => (!(e.Tags.Contains(\"VIP\")))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ListAnyCheck()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Children.Any(c => c.Age > 18);
|
||||
Assert.Equal("e => e.Children.Any(c => (c.Age > 18))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ListNotAnyCheck()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => !e.Children.Any(c => c.Age > 18);
|
||||
Assert.Equal("e => (!(e.Children.Any(c => (c.Age > 18))))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_EntitySubPropertyCheck()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Address.City == "New York";
|
||||
Assert.Equal("e => (e.Address.City == \"New York\")", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_ComplexExpressionWithProperties()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => e.Age > 18 && e.Tags.Contains("Member") || e.Address.City == "London";
|
||||
Assert.Equal("e => (((e.Age > 18) && e.Tags.Contains(\"Member\")) || (e.Address.City == \"London\"))", _serializer.Serialize(expr));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Serializes_NotContains()
|
||||
{
|
||||
Expression<Func<TestEntity, bool>> expr = e => !e.Tags.Contains("Member");
|
||||
Assert.Equal("e => (!(e.Tags.Contains(\"Member\")))", _serializer.Serialize(expr));
|
||||
}
|
||||
}
|
||||
}
|
||||
218
Radzen.Blazor.Tests/FieldsetTests.cs
Normal file
218
Radzen.Blazor.Tests/FieldsetTests.cs
Normal file
@@ -0,0 +1,218 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class FieldsetTests
|
||||
{
|
||||
[Fact]
|
||||
public void Fieldset_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-fieldset", component.Markup);
|
||||
Assert.Contains(@$"rz-fieldset-content-wrapper", component.Markup);
|
||||
Assert.Contains(@$"rz-fieldset-content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, value));
|
||||
|
||||
Assert.Contains(@$"<span class=""rz-fieldset-legend-text"">{value}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, value));
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rzi"">{value}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_ChildContentParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var value = "MyChildContent";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ChildContent, value));
|
||||
|
||||
Assert.Contains(@$"{value}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_HeaderTemplateParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var value = "MyHeaderTemplate";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.HeaderTemplate, value));
|
||||
|
||||
Assert.Contains(@$"{value}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_AllowCollapseParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var classes = @"rz-fieldset-toggler";
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.DoesNotContain(classes, component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
|
||||
|
||||
Assert.Contains(classes, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_CollapsedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
|
||||
|
||||
Assert.Contains(@"<span class=""notranslate rz-fieldset-toggler rzi rzi-w rzi-minus""></span>", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Collapsed, true));
|
||||
|
||||
Assert.Contains(@"<span class=""notranslate rz-fieldset-toggler rzi rzi-w rzi-plus""></span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Raises_ExpandAndCollapseEvents()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add(p => p.Collapse, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find("a").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
|
||||
raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Expand, args => { raised = true; }));
|
||||
|
||||
component.Find("a").Click();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_Renders_SummaryWhenCollapsed()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, true);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"false",
|
||||
component.Find(".rz-fieldset-content-summary").ParentElement.ParentElement.Attributes.First(attr => attr.Name == "aria-hidden").Value
|
||||
);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Fieldset_DoesNotRender_SummaryWhenOpen()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFieldset>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, false);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"true",
|
||||
component.Find(".rz-fieldset-content-summary").ParentElement.ParentElement.Attributes.First(attr => attr.Name == "aria-hidden").Value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
182
Radzen.Blazor.Tests/FileInputTests.cs
Normal file
182
Radzen.Blazor.Tests/FileInputTests.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class FileInputTests
|
||||
{
|
||||
[Fact]
|
||||
public void FileInput_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>();
|
||||
|
||||
Assert.Contains(@"rz-fileupload", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_ChooseButton()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>();
|
||||
|
||||
Assert.Contains("rz-fileupload-choose", component.Markup);
|
||||
Assert.Contains("rz-button", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_ChooseText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ChooseText, "Select File");
|
||||
});
|
||||
|
||||
Assert.Contains("Select File", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_DefaultChooseText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>();
|
||||
|
||||
Assert.Contains("Choose", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_Accept()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Accept, "application/pdf");
|
||||
});
|
||||
|
||||
Assert.Contains("accept=\"application/pdf\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_DefaultAccept()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>();
|
||||
|
||||
Assert.Contains("accept=\"image/*\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_FileInputElement()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>();
|
||||
|
||||
Assert.Contains("type=\"file\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_Title_WhenSet()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Title, "MyDocument.pdf");
|
||||
parameters.Add(p => p.Value, "data:application/pdf;base64,test");
|
||||
});
|
||||
|
||||
Assert.Contains("MyDocument.pdf", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_FileName_WhenTitleNotSet()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.FileName, "document.pdf");
|
||||
parameters.Add(p => p.Value, "data:application/pdf;base64,test");
|
||||
});
|
||||
|
||||
Assert.Contains("document.pdf", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_DeleteButton_WhenValueSet()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, "data:text/plain;base64,test");
|
||||
});
|
||||
|
||||
Assert.Contains("rz-icon-trash", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_CustomDeleteText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.DeleteText, "Remove File");
|
||||
parameters.Add(p => p.Value, "data:text/plain;base64,test");
|
||||
});
|
||||
|
||||
Assert.Contains("title=\"Remove File\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_ImagePreview_ForImageFile()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, "data:image/png;base64,test");
|
||||
});
|
||||
|
||||
Assert.Contains("<img", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FileInput_Renders_ImageAlternateText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenFileInput<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ImageAlternateText, "User Photo");
|
||||
parameters.Add(p => p.Value, "data:image/png;base64,test");
|
||||
});
|
||||
|
||||
Assert.Contains("alt=\"User Photo\"", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
163
Radzen.Blazor.Tests/FormFieldTests.cs
Normal file
163
Radzen.Blazor.Tests/FormFieldTests.cs
Normal file
@@ -0,0 +1,163 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class FormFieldTests
|
||||
{
|
||||
[Fact]
|
||||
public void FormField_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>();
|
||||
|
||||
Assert.Contains(@"rz-form-field", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Text()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Text, "Email Address");
|
||||
});
|
||||
|
||||
Assert.Contains("Email Address", component.Markup);
|
||||
Assert.Contains("rz-form-field-label", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Variant_Outlined()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Variant, Variant.Outlined);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-variant-outlined", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Variant_Filled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Variant, Variant.Filled);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-variant-filled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Variant_Flat()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Variant, Variant.Flat);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-variant-flat", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Variant_Text()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Variant, Variant.Text);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-variant-text", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_AllowFloatingLabel_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFloatingLabel, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-floating-label", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_AllowFloatingLabel_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFloatingLabel, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-floating-label", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Component_Attribute()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Component, "email-input");
|
||||
});
|
||||
|
||||
Assert.Contains("for=\"email-input\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Helper()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Helper, builder => builder.AddContent(0, "Enter your email address"));
|
||||
});
|
||||
|
||||
Assert.Contains("rz-form-field-helper", component.Markup);
|
||||
Assert.Contains("Enter your email address", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_Start()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Start, builder => builder.AddMarkupContent(0, "<span>Start</span>"));
|
||||
});
|
||||
|
||||
Assert.Contains("rz-form-field-start", component.Markup);
|
||||
Assert.Contains("Start", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_End()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.End, builder => builder.AddMarkupContent(0, "<span>End</span>"));
|
||||
});
|
||||
|
||||
Assert.Contains("rz-form-field-end", component.Markup);
|
||||
Assert.Contains("End", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FormField_Renders_FormFieldContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenFormField>();
|
||||
|
||||
Assert.Contains("rz-form-field-content", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
103
Radzen.Blazor.Tests/HeadingTests.cs
Normal file
103
Radzen.Blazor.Tests/HeadingTests.cs
Normal file
@@ -0,0 +1,103 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class HeadingTests
|
||||
{
|
||||
[Fact]
|
||||
public void Heading_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
Assert.Contains(@"rz-heading", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
var text = "Test Heading";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(text, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_H1_ByDefault()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
var text = "Heading Text";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains("<h1", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_H2_Size()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
var text = "Heading 2";
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Size, "H2");
|
||||
});
|
||||
|
||||
Assert.Contains("<h2", component.Markup);
|
||||
Assert.Contains(text, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_H3_Size()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H3"));
|
||||
|
||||
Assert.Contains("<h3", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_H4_Size()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H4"));
|
||||
|
||||
Assert.Contains("<h4", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_H5_Size()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H5"));
|
||||
|
||||
Assert.Contains("<h5", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Heading_Renders_H6_Size()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenHeading>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, "H6"));
|
||||
|
||||
Assert.Contains("<h6", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
104
Radzen.Blazor.Tests/HtmlEditorTests.cs
Normal file
104
Radzen.Blazor.Tests/HtmlEditorTests.cs
Normal file
@@ -0,0 +1,104 @@
|
||||
using Bunit;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class HtmlEditorTests
|
||||
{
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>();
|
||||
|
||||
Assert.Contains(@"rz-html-editor", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_ShowToolbar_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowToolbar, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-html-editor-toolbar", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_ShowToolbar_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowToolbar, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-html-editor-toolbar", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_Mode_Design()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Mode, HtmlEditorMode.Design);
|
||||
});
|
||||
|
||||
// Design mode shows the content editable div
|
||||
Assert.Contains("contenteditable", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_Mode_Source()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Mode, HtmlEditorMode.Source);
|
||||
});
|
||||
|
||||
// Source mode shows the textarea for HTML editing
|
||||
Assert.Contains("rz-html-editor-source", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_Disabled_Attribute()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HtmlEditor_Renders_ContentArea()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.Services.AddScoped<DialogService>();
|
||||
var component = ctx.RenderComponent<RadzenHtmlEditor>();
|
||||
|
||||
Assert.Contains("rz-html-editor-content", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
97
Radzen.Blazor.Tests/IconTests.cs
Normal file
97
Radzen.Blazor.Tests/IconTests.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class IconTests
|
||||
{
|
||||
[Fact]
|
||||
public void Icon_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"class=""notranslate rzi""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_Renders_IconStyleClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, IconStyle.Primary));
|
||||
|
||||
Assert.Contains(@$"rzi-primary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_Renders_IconColor()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconColor, Colors.Primary));
|
||||
|
||||
Assert.Contains(@$"color:", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_NotRenders_IconStyleClass_WhenNull()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconStyle, null));
|
||||
|
||||
Assert.DoesNotContain(@$"rzi-primary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_NotRenders_IconColor_WhenNull()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(icon => icon.IconColor, null));
|
||||
|
||||
Assert.DoesNotContain(@$"color:", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
64
Radzen.Blazor.Tests/ImageTests.cs
Normal file
64
Radzen.Blazor.Tests/ImageTests.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ImageTests
|
||||
{
|
||||
[Fact]
|
||||
public void Image_Renders_PathParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenImage>();
|
||||
|
||||
var path = "Test.png";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Path, path));
|
||||
|
||||
Assert.Contains(@$"<img src=""{path}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Image_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenImage>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Image_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenImage>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Image_Raises_ClickEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenImage>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Click, args => { clicked = true; }));
|
||||
|
||||
component.Find("img").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
62
Radzen.Blazor.Tests/LabelTests.cs
Normal file
62
Radzen.Blazor.Tests/LabelTests.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class LabelTests
|
||||
{
|
||||
[Fact]
|
||||
public void Label_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLabel>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, value));
|
||||
|
||||
Assert.Contains(@$">{value}</label>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Label_Renders_ComponentParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLabel>();
|
||||
|
||||
var value = "test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Component, value));
|
||||
|
||||
Assert.Contains(@$"for=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Label_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLabel>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Label_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLabel>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
107
Radzen.Blazor.Tests/LinkTests.cs
Normal file
107
Radzen.Blazor.Tests/LinkTests.cs
Normal file
@@ -0,0 +1,107 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class LinkTests
|
||||
{
|
||||
[Fact]
|
||||
public void Link_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLink>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Link_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLink>();
|
||||
|
||||
var text = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
var textElement = component.Find(".rz-link-text");
|
||||
|
||||
Assert.NotNull(textElement);
|
||||
Assert.Equal(text, textElement.TextContent.Trim());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Link_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLink>();
|
||||
|
||||
var icon = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Link_Renders_PathParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLink>();
|
||||
|
||||
var path = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Path, path));
|
||||
|
||||
Assert.Contains(@$"<a href=""{path}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Link_Renders_TargetParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLink>();
|
||||
|
||||
var target = "_blank";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Target, target));
|
||||
|
||||
Assert.Contains(@$"target=""{target}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Link_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLink>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains("class=\"rz-link rz-link-disabled active\"", component.Markup);
|
||||
|
||||
Assert.DoesNotContain("href=", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Icon_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenIcon>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
197
Radzen.Blazor.Tests/ListBoxTests.cs
Normal file
197
Radzen.Blazor.Tests/ListBoxTests.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ListBoxTests
|
||||
{
|
||||
class Item
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>();
|
||||
|
||||
Assert.Contains(@"rz-listbox", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_WithData_SimpleList()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Apple", "Banana", "Cherry" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenListBox<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("Apple", component.Markup);
|
||||
Assert.Contains("Banana", component.Markup);
|
||||
Assert.Contains("Cherry", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_WithData_CustomTextValueProperties()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<Item>
|
||||
{
|
||||
new Item { Id = 1, Name = "First Item" },
|
||||
new Item { Id = 2, Name = "Second Item" }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
parameters.Add(p => p.TextProperty, "Name");
|
||||
parameters.Add(p => p.ValueProperty, "Id");
|
||||
});
|
||||
|
||||
Assert.Contains("First Item", component.Markup);
|
||||
Assert.Contains("Second Item", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_AllowFiltering()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
parameters.Add(p => p.Data, new List<string> { "Item1", "Item2" });
|
||||
});
|
||||
|
||||
Assert.Contains("rz-listbox-filter", component.Markup);
|
||||
Assert.Contains("rz-listbox-header", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_Disabled_Attribute()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_Multiple_WithSelectAll()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<IEnumerable<int>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.SelectAllText, "Select All Items");
|
||||
parameters.Add(p => p.Data, new List<string> { "Item1", "Item2" });
|
||||
});
|
||||
|
||||
Assert.Contains("Select All Items", component.Markup);
|
||||
Assert.Contains("rz-chkbox", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_FilterPlaceholder()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Placeholder, "Select an item");
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
parameters.Add(p => p.Data, new List<string> { "Item1", "Item2" });
|
||||
});
|
||||
|
||||
Assert.Contains("Select an item", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_Multiple_WithCheckboxes()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1", "Item2" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenListBox<IEnumerable<string>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
// Multiple selection shows checkboxes in header
|
||||
Assert.Contains("rz-listbox-header-w-checkbox", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_ReadOnly()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ReadOnly, true);
|
||||
});
|
||||
|
||||
Assert.Contains("readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_TabIndex()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>();
|
||||
|
||||
Assert.Contains("tabindex=", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_ListWrapper()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<string> { "Item1" };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenListBox<string>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, data);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-listbox-list-wrapper", component.Markup);
|
||||
Assert.Contains("rz-listbox-list", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ListBox_Renders_SearchAriaLabel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenListBox<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
parameters.Add(p => p.SearchAriaLabel, "Search items");
|
||||
parameters.Add(p => p.Data, new List<string> { "Item1" });
|
||||
});
|
||||
|
||||
Assert.Contains("aria-label=\"Search items\"", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
242
Radzen.Blazor.Tests/LoginTests.cs
Normal file
242
Radzen.Blazor.Tests/LoginTests.cs
Normal file
@@ -0,0 +1,242 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class LoginTests
|
||||
{
|
||||
[Fact]
|
||||
public void Login_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_UsernameLabel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(p => {
|
||||
p.AddUnmatched("id", "login");
|
||||
});
|
||||
|
||||
var label = component.Find($@"label[for=""login-username""]");
|
||||
Assert.NotNull(label);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_UsernameInput()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
Assert.Contains(@$"<input name=""Username""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Raises_LoginEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Username, "user");
|
||||
parameters.Add(p => p.Password, "pwd");
|
||||
parameters.Add(p => p.Login, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_NotRaises_LoginEvent_WhenEmptyUsernameOrPasword()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Login, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.True(!clicked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_LoginTextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.LoginText, "Test");
|
||||
});
|
||||
|
||||
Assert.Contains(@$">Test</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_AllowResetPasswordParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowResetPassword, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"Forgot password?</a>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_ResetPasswordTextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowResetPassword, true);
|
||||
parameters.Add(p => p.ResetPasswordText, "Test");
|
||||
});
|
||||
|
||||
Assert.Contains(@$"Test</a>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_AllowRegisterParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowRegister, true);
|
||||
});
|
||||
|
||||
Assert.Contains(@$">Sign up</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_RegisterTextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowRegister, true);
|
||||
parameters.Add(p => p.RegisterText, "Test");
|
||||
});
|
||||
|
||||
Assert.Contains(@$">Test</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Renders_RegisterMessageTextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowRegister, true);
|
||||
parameters.Add(p => p.RegisterMessageText, "Test");
|
||||
});
|
||||
|
||||
Assert.Contains(@$"Test", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Raises_RegisterEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowRegister, true);
|
||||
parameters.Add(p => p.Register, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find(".rz-secondary").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Raises_ResetPasswordEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowResetPassword, true);
|
||||
parameters.Add(p => p.Username, "user");
|
||||
parameters.Add(p => p.ResetPassword, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("a").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Login_Raises_ResetPasswordEvent_WhenEmptyUsername()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenLogin>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.AllowResetPassword, true);
|
||||
parameters.Add(p => p.ResetPassword, args => { clicked = true; });
|
||||
});
|
||||
|
||||
component.Find("a").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
314
Radzen.Blazor.Tests/Markdown/BlockQuoteTests.cs
Normal file
314
Radzen.Blazor.Tests/Markdown/BlockQuoteTests.cs
Normal file
@@ -0,0 +1,314 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class BlockQuoteTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_BasicBlockQuote()
|
||||
{
|
||||
|
||||
Assert.Equal(@"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>", ToXml(@"> foo"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"> # Foo
|
||||
> bar
|
||||
> baz", @"<document>
|
||||
<block_quote>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"># Foo
|
||||
>bar
|
||||
> baz", @"<document>
|
||||
<block_quote>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@" > # Foo
|
||||
> bar
|
||||
> baz", @"<document>
|
||||
<block_quote>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@" > # Foo
|
||||
> bar
|
||||
> baz", @"<document>
|
||||
<code_block>> # Foo
|
||||
> bar
|
||||
> baz
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"> # Foo
|
||||
> bar
|
||||
baz", @"<document>
|
||||
<block_quote>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> bar
|
||||
baz
|
||||
> foo", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
<softbreak />
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
---", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"> - foo
|
||||
- bar", @"<document>
|
||||
<block_quote>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</block_quote>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
bar", @"<document>
|
||||
<block_quote>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
</block_quote>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"> ```
|
||||
foo
|
||||
```", @"<document>
|
||||
<block_quote>
|
||||
<code_block></code_block>
|
||||
</block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<code_block></code_block>
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
- bar", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>- bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@">", @"<document>
|
||||
<block_quote />
|
||||
</document>")]
|
||||
[InlineData(@">
|
||||
>
|
||||
> ", @"<document>
|
||||
<block_quote />
|
||||
</document>")]
|
||||
[InlineData(@">
|
||||
> foo
|
||||
> ", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
|
||||
> bar", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
>
|
||||
> bar", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
> bar", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> aaa
|
||||
***
|
||||
> bbb", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<thematic_break />
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> bar
|
||||
baz", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> bar
|
||||
|
||||
baz", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"> bar
|
||||
>
|
||||
baz", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"> > > foo
|
||||
bar", @"<document>
|
||||
<block_quote>
|
||||
<block_quote>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</block_quote>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@">>> foo
|
||||
> bar
|
||||
>>baz", @"<document>
|
||||
<block_quote>
|
||||
<block_quote>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</block_quote>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> code
|
||||
|
||||
> not code", @"<document>
|
||||
<block_quote>
|
||||
<code_block>code
|
||||
</code_block>
|
||||
</block_quote>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>not code</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
public void Parse_BlockQuote(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
175
Radzen.Blazor.Tests/Markdown/CodeTests.cs
Normal file
175
Radzen.Blazor.Tests/Markdown/CodeTests.cs
Normal file
@@ -0,0 +1,175 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class CodeTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("`foo`",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code>foo</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("`` foo ` bar ``",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code>foo ` bar</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("` `` `",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code>``</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_BasicCode_ReturnsCodeNode(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("` `` `",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code> `` </code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("` a`",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code> a</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"` `
|
||||
` `",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code> </code>
|
||||
<softbreak />
|
||||
<code> </code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_CodeWithSpaces_PreservesSpaces(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"``
|
||||
foo
|
||||
bar
|
||||
baz
|
||||
``",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code>foo bar baz</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"``
|
||||
foo
|
||||
``",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code>foo </code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"`foo bar
|
||||
baz`",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<code>foo bar baz</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
|
||||
public void Parse_CodeWithLineBreaks_ConvertsToSpace(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("`foo\\`bar`", @"<document>
|
||||
<paragraph>
|
||||
<code>foo\</code>
|
||||
<text>bar</text>
|
||||
<text>`</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("``foo`bar``", @"<document>
|
||||
<paragraph>
|
||||
<code>foo`bar</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("` foo `` bar `", @"<document>
|
||||
<paragraph>
|
||||
<code>foo `` bar</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_CodeWithBacktics(string mardown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(mardown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("*foo`*`", @"<document>
|
||||
<paragraph>
|
||||
<text>*</text>
|
||||
<text>foo</text>
|
||||
<code>*</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[not a `link](/foo`)",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>not a </text>
|
||||
<code>link](/foo</code>
|
||||
<text>)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("`<https://foo.bar.`baz>`",@"<document>
|
||||
<paragraph>
|
||||
<code><https://foo.bar.</code>
|
||||
<text>baz></text>
|
||||
<text>`</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_CodePrecedence(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("```foo``", @"<document>
|
||||
<paragraph>
|
||||
<text>```</text>
|
||||
<text>foo</text>
|
||||
<text>``</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("`foo", @"<document>
|
||||
<paragraph>
|
||||
<text>`</text>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("`foo``bar``", @"<document>
|
||||
<paragraph>
|
||||
<text>`</text>
|
||||
<text>foo</text>
|
||||
<code>bar</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_UnmatchingBacktics(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
272
Radzen.Blazor.Tests/Markdown/EmphasisTests.cs
Normal file
272
Radzen.Blazor.Tests/Markdown/EmphasisTests.cs
Normal file
@@ -0,0 +1,272 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class EmphasisTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"**foo** bar
|
||||
baz",@"<document>
|
||||
<paragraph>
|
||||
<strong>
|
||||
<text>foo</text>
|
||||
</strong>
|
||||
<text> bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("*foo bar*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo bar</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("a * foo bar*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>a </text>
|
||||
<text>*</text>
|
||||
<text> foo bar</text>
|
||||
<text>*</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("a*\"foo\"*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
<text>*</text>
|
||||
<text>""foo""</text>
|
||||
<text>*</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("* a *",
|
||||
@"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a </text>
|
||||
<text>*</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData("foo*bar*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<emph>
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("5*6*78",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>5</text>
|
||||
<emph>
|
||||
<text>6</text>
|
||||
</emph>
|
||||
<text>78</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_foo bar_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo bar</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_ foo bar_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>_</text>
|
||||
<text> foo bar</text>
|
||||
<text>_</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("a_\"foo\"_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
<text>_</text>
|
||||
<text>""foo""</text>
|
||||
<text>_</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("foo_bar_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<text>_</text>
|
||||
<text>bar</text>
|
||||
<text>_</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("5_6_78",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>5</text>
|
||||
<text>_</text>
|
||||
<text>6</text>
|
||||
<text>_</text>
|
||||
<text>78</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("пристаням_стремятся_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>пристаням</text>
|
||||
<text>_</text>
|
||||
<text>стремятся</text>
|
||||
<text>_</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("aa_\"bb\"_cc",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>aa</text>
|
||||
<text>_</text>
|
||||
<text>""bb""</text>
|
||||
<text>_</text>
|
||||
<text>cc</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("foo-_(bar)_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>foo-</text>
|
||||
<emph>
|
||||
<text>(bar)</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_foo*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>_</text>
|
||||
<text>foo</text>
|
||||
<text>*</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("*foo bar *",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>*</text>
|
||||
<text>foo bar </text>
|
||||
<text>*</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("*foo bar\nbaz*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("*(*foo)",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>*</text>
|
||||
<text>(</text>
|
||||
<text>*</text>
|
||||
<text>foo)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("*(*foo*)*",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>(</text>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
</emph>
|
||||
<text>)</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("*foo*bar",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
</emph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_foo bar _",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>_</text>
|
||||
<text>foo bar </text>
|
||||
<text>_</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_(_foo_)_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>(</text>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
</emph>
|
||||
<text>)</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_foo_bar",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>_</text>
|
||||
<text>foo</text>
|
||||
<text>_</text>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_пристаням_стремятся",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>_</text>
|
||||
<text>пристаням</text>
|
||||
<text>_</text>
|
||||
<text>стремятся</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_foo_bar_baz_",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
<text>_</text>
|
||||
<text>bar</text>
|
||||
<text>_</text>
|
||||
<text>baz</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("_(bar)_.",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>(bar)</text>
|
||||
</emph>
|
||||
<text>.</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_EmphasisRules_AdheresToCommonMarkSpec(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
264
Radzen.Blazor.Tests/Markdown/FencedCodeBlockTests.cs
Normal file
264
Radzen.Blazor.Tests/Markdown/FencedCodeBlockTests.cs
Normal file
@@ -0,0 +1,264 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class FencedCodeBlockTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_BasicFencedCodeBlock()
|
||||
{
|
||||
Assert.Equal(@"<document>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
</document>", ToXml(@"```
|
||||
foo
|
||||
```"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"```
|
||||
<
|
||||
>
|
||||
```", @"<document>
|
||||
<code_block><
|
||||
>
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"~~~
|
||||
<
|
||||
>
|
||||
~~~", @"<document>
|
||||
<code_block><
|
||||
>
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"``
|
||||
foo
|
||||
``", @"<document>
|
||||
<paragraph>
|
||||
<code>foo</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
aaa
|
||||
~~~
|
||||
```", @"<document>
|
||||
<code_block>aaa
|
||||
~~~
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"~~~
|
||||
aaa
|
||||
```
|
||||
~~~", @"<document>
|
||||
<code_block>aaa
|
||||
```
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"````
|
||||
aaa
|
||||
```
|
||||
``````", @"<document>
|
||||
<code_block>aaa
|
||||
```
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"~~~~
|
||||
aaa
|
||||
~~~
|
||||
~~~~", @"<document>
|
||||
<code_block>aaa
|
||||
~~~
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"```", @"<document>
|
||||
<code_block></code_block>
|
||||
</document>")]
|
||||
[InlineData(@"`````
|
||||
|
||||
```
|
||||
aaa", @"<document>
|
||||
<code_block>
|
||||
```
|
||||
aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"> ```
|
||||
> aaa
|
||||
|
||||
bbb", @"<document>
|
||||
<block_quote>
|
||||
<code_block>aaa
|
||||
</code_block>
|
||||
</block_quote>
|
||||
<paragraph>
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
|
||||
|
||||
```", @"<document>
|
||||
<code_block>
|
||||
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
```", @"<document>
|
||||
<code_block></code_block>
|
||||
</document>")]
|
||||
[InlineData(@" ```
|
||||
aaa
|
||||
aaa
|
||||
```", @"<document>
|
||||
<code_block>aaa
|
||||
aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" ```
|
||||
aaa
|
||||
aaa
|
||||
aaa
|
||||
```", @"<document>
|
||||
<code_block>aaa
|
||||
aaa
|
||||
aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" ```
|
||||
aaa
|
||||
aaa
|
||||
aaa
|
||||
```", @"<document>
|
||||
<code_block>aaa
|
||||
aaa
|
||||
aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" ```
|
||||
aaa
|
||||
```", @"<document>
|
||||
<code_block>```
|
||||
aaa
|
||||
```
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
aaa
|
||||
```", @"<document>
|
||||
<code_block>aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" ```
|
||||
aaa
|
||||
````", @"<document>
|
||||
<code_block>aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
aaa
|
||||
```", @"<document>
|
||||
<code_block>aaa
|
||||
```
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"``` ```
|
||||
aaa", @"<document>
|
||||
<paragraph>
|
||||
<code> </code>
|
||||
<softbreak />
|
||||
<text>aaa</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"~~~~~~
|
||||
aaa
|
||||
~~~ ~~", @"<document>
|
||||
<code_block>aaa
|
||||
~~~ ~~
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
```
|
||||
bar
|
||||
```
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
---
|
||||
~~~
|
||||
bar
|
||||
~~~
|
||||
# baz", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
<heading level=""1"">
|
||||
<text>baz</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"```ruby
|
||||
def foo(x)
|
||||
return 3
|
||||
end
|
||||
```", @"<document>
|
||||
<code_block info=""ruby"">def foo(x)
|
||||
return 3
|
||||
end
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"~~~~ ruby startline=3 $%@#$
|
||||
def foo(x)
|
||||
return 3
|
||||
end
|
||||
~~~~~~~", @"<document>
|
||||
<code_block info=""ruby startline=3 $%@#$"">def foo(x)
|
||||
return 3
|
||||
end
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"````;
|
||||
````", @"<document>
|
||||
<code_block info="";""></code_block>
|
||||
</document>")]
|
||||
[InlineData(@"``` aa ```
|
||||
foo", @"<document>
|
||||
<paragraph>
|
||||
<code>aa</code>
|
||||
<softbreak />
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"~~~ aa ``` ~~~
|
||||
foo
|
||||
~~~", @"<document>
|
||||
<code_block info=""aa ``` ~~~"">foo
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
``` aaa
|
||||
```", @"<document>
|
||||
<code_block>``` aaa
|
||||
</code_block>
|
||||
</document>")]
|
||||
public void Parse_FencedCodeBlock(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
132
Radzen.Blazor.Tests/Markdown/HardLineBreakTests.cs
Normal file
132
Radzen.Blazor.Tests/Markdown/HardLineBreakTests.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class HardLineBreakTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"foo
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("foo \r\nbaz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo\
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
bar", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo\
|
||||
bar", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"*foo
|
||||
bar*", @"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"*foo\
|
||||
bar*", @"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
<linebreak />
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"`code\
|
||||
span`", @"<document>
|
||||
<paragraph>
|
||||
<code>code\ span</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"`code
|
||||
span`", @"<document>
|
||||
<paragraph>
|
||||
<code>code span</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a href=""foo
|
||||
bar"">", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><a href=""foo
|
||||
bar""></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a href=""foo\
|
||||
bar"">", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><a href=""foo\
|
||||
bar""></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo\", @"<document>
|
||||
<paragraph>
|
||||
<text>foo\</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo ", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"### foo\", @"<document>
|
||||
<heading level=""3"">
|
||||
<text>foo\</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"### foo ", @"<document>
|
||||
<heading level=""3"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
public void Parse_HardLineBreak(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
511
Radzen.Blazor.Tests/Markdown/HeadingTests.cs
Normal file
511
Radzen.Blazor.Tests/Markdown/HeadingTests.cs
Normal file
@@ -0,0 +1,511 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class HeadingTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_BasicAtxHeading()
|
||||
{
|
||||
Assert.Equal(@"<document>
|
||||
<heading level=""1"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>", ToXml("# foo"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"# foo
|
||||
## foo
|
||||
### foo
|
||||
#### foo
|
||||
##### foo
|
||||
###### foo", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""2"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""3"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""4"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""5"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""6"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"####### foo", @"<document>
|
||||
<paragraph>
|
||||
<text>####### foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"#5 bolt
|
||||
|
||||
#hashtag", @"<document>
|
||||
<paragraph>
|
||||
<text>#5 bolt</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>#hashtag</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"\## foo", @"<document>
|
||||
<paragraph>
|
||||
<text>#</text>
|
||||
<text># foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"# foo *bar* \*baz\*", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>foo </text>
|
||||
<emph>
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
<text> </text>
|
||||
<text>*</text>
|
||||
<text>baz</text>
|
||||
<text>*</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"# foo ", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@" ### foo
|
||||
## foo
|
||||
# foo", @"<document>
|
||||
<heading level=""3"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""2"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""1"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@" # foo", @"<document>
|
||||
<code_block># foo
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
# bar", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text># bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"## foo ##
|
||||
### bar ###", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""3"">
|
||||
<text>bar</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"# foo ##################################
|
||||
##### foo ##", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<heading level=""5"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"### foo ### ", @"<document>
|
||||
<heading level=""3"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"### foo ### b", @"<document>
|
||||
<heading level=""3"">
|
||||
<text>foo ### b</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"# foo#", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>foo#</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"### foo \###
|
||||
## foo #\##
|
||||
# foo \#", @"<document>
|
||||
<heading level=""3"">
|
||||
<text>foo </text>
|
||||
<text>#</text>
|
||||
<text>##</text>
|
||||
</heading>
|
||||
<heading level=""2"">
|
||||
<text>foo #</text>
|
||||
<text>#</text>
|
||||
<text>#</text>
|
||||
</heading>
|
||||
<heading level=""1"">
|
||||
<text>foo </text>
|
||||
<text>#</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"****
|
||||
## foo
|
||||
****", @"<document>
|
||||
<thematic_break />
|
||||
<heading level=""2"">
|
||||
<text>foo</text>
|
||||
</heading>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"Foo bar
|
||||
# baz
|
||||
Bar foo", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo bar</text>
|
||||
</paragraph>
|
||||
<heading level=""1"">
|
||||
<text>baz</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>Bar foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"##
|
||||
#
|
||||
### ###", @"<document>
|
||||
<heading level=""2"" />
|
||||
<heading level=""1"" />
|
||||
<heading level=""3"" />
|
||||
</document>")]
|
||||
public void Parse_AtxHeading(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"Foo *bar*
|
||||
=========
|
||||
|
||||
Foo *baz*
|
||||
---------", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>Foo </text>
|
||||
<emph>
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
</heading>
|
||||
<heading level=""2"">
|
||||
<text>Foo </text>
|
||||
<emph>
|
||||
<text>baz</text>
|
||||
</emph>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"Foo *bar
|
||||
baz*
|
||||
====", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>Foo </text>
|
||||
<emph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</emph>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@" Foo *bar
|
||||
baz*
|
||||
====", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>Foo </text>
|
||||
<emph>
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</emph>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
-------------------------
|
||||
|
||||
Foo
|
||||
=", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@" Foo
|
||||
---
|
||||
|
||||
Foo
|
||||
-----
|
||||
|
||||
Foo
|
||||
===", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@" Foo
|
||||
---
|
||||
|
||||
Foo
|
||||
---", @"<document>
|
||||
<code_block>Foo
|
||||
---
|
||||
|
||||
Foo
|
||||
</code_block>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
---- ", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
---", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>---</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
= =
|
||||
|
||||
Foo
|
||||
--- -", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>= =</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
-----", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"Foo\
|
||||
----", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>Foo\</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"`Foo
|
||||
----
|
||||
`
|
||||
|
||||
<a title=""a lot
|
||||
---
|
||||
of dashes""/>", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>`</text>
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>`</text>
|
||||
</paragraph>
|
||||
<heading level=""2"">
|
||||
<text><a title=""a lot</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>of dashes""/></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"> Foo
|
||||
---", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
bar
|
||||
===", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>===</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"- Foo
|
||||
---", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
Bar
|
||||
---", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>Bar</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"---
|
||||
Foo
|
||||
---
|
||||
Bar
|
||||
---
|
||||
Baz", @"<document>
|
||||
<thematic_break />
|
||||
<heading level=""2"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
<heading level=""2"">
|
||||
<text>Bar</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>Baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"
|
||||
====", @"<document>
|
||||
<paragraph>
|
||||
<text>====</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"---
|
||||
---", @"<document>
|
||||
<thematic_break />
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
-----", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@" foo
|
||||
---", @"<document>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"> foo
|
||||
-----", @"<document>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"\> foo
|
||||
------", @"<document>
|
||||
<heading level=""2"">
|
||||
<text>> foo</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
|
||||
bar
|
||||
---
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
<heading level=""2"">
|
||||
<text>bar</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
bar
|
||||
|
||||
---
|
||||
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
<thematic_break />
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
bar
|
||||
* * *
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
<thematic_break />
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
bar
|
||||
\---
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
<softbreak />
|
||||
<text>-</text>
|
||||
<text>--</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_SetExtHeading(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
487
Radzen.Blazor.Tests/Markdown/HtmlBlockTests.cs
Normal file
487
Radzen.Blazor.Tests/Markdown/HtmlBlockTests.cs
Normal file
@@ -0,0 +1,487 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class HtmlBlockTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"<table><tr><td>
|
||||
<pre>
|
||||
**Hello**,
|
||||
|
||||
_world_.
|
||||
</pre>
|
||||
</td></tr></table>", @"<document>
|
||||
<html_block><table><tr><td>
|
||||
<pre>
|
||||
**Hello**,</html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>world</text>
|
||||
</emph>
|
||||
<text>.</text>
|
||||
<softbreak />
|
||||
<html_inline></pre></html_inline>
|
||||
</paragraph>
|
||||
<html_block></td></tr></table></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<table>
|
||||
<tr>
|
||||
<td>
|
||||
hi
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
okay.", @"<document>
|
||||
<html_block><table>
|
||||
<tr>
|
||||
<td>
|
||||
hi
|
||||
</td>
|
||||
</tr>
|
||||
</table></html_block>
|
||||
<paragraph>
|
||||
<text>okay.</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" <div>
|
||||
*hello*
|
||||
<foo><a>", @"<document>
|
||||
<html_block> <div>
|
||||
*hello*
|
||||
<foo><a></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"</div>
|
||||
*foo*", @"<document>
|
||||
<html_block></div>
|
||||
*foo*</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<DIV CLASS=""foo"">
|
||||
|
||||
*Markdown*
|
||||
|
||||
</DIV>", @"<document>
|
||||
<html_block><DIV CLASS=""foo""></html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>Markdown</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
<html_block></DIV></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div id=""foo""
|
||||
class=""bar"">
|
||||
</div>", @"<document>
|
||||
<html_block><div id=""foo""
|
||||
class=""bar"">
|
||||
</div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div id=""foo"" class=""bar
|
||||
baz"">
|
||||
</div>", @"<document>
|
||||
<html_block><div id=""foo"" class=""bar
|
||||
baz"">
|
||||
</div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div>
|
||||
*foo*
|
||||
|
||||
*bar*", @"<document>
|
||||
<html_block><div>
|
||||
*foo*</html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<div id=""foo""
|
||||
*hi*", @"<document>
|
||||
<html_block><div id=""foo""
|
||||
*hi*</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div class
|
||||
foo", @"<document>
|
||||
<html_block><div class
|
||||
foo</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div *???-&&&-<---
|
||||
*foo*", @"<document>
|
||||
<html_block><div *???-&&&-<---
|
||||
*foo*</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div><a href=""bar"">*foo*</a></div>", @"<document>
|
||||
<html_block><div><a href=""bar"">*foo*</a></div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<table><tr><td>
|
||||
foo
|
||||
</td></tr></table>", @"<document>
|
||||
<html_block><table><tr><td>
|
||||
foo
|
||||
</td></tr></table></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div></div>
|
||||
``` c
|
||||
int x = 33;
|
||||
```", @"<document>
|
||||
<html_block><div></div>
|
||||
``` c
|
||||
int x = 33;
|
||||
```</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<a href=""foo"">
|
||||
*bar*
|
||||
</a>", @"<document>
|
||||
<html_block><a href=""foo"">
|
||||
*bar*
|
||||
</a></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<Warning>
|
||||
*bar*
|
||||
</Warning>", @"<document>
|
||||
<html_block><Warning>
|
||||
*bar*
|
||||
</Warning></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<i class=""foo"">
|
||||
*bar*
|
||||
</i>", @"<document>
|
||||
<html_block><i class=""foo"">
|
||||
*bar*
|
||||
</i></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"</ins>
|
||||
*bar*", @"<document>
|
||||
<html_block></ins>
|
||||
*bar*</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<del>
|
||||
*foo*
|
||||
</del>", @"<document>
|
||||
<html_block><del>
|
||||
*foo*
|
||||
</del></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<del>
|
||||
|
||||
*foo*
|
||||
|
||||
</del>", @"<document>
|
||||
<html_block><del></html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
<html_block></del></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<del>*foo*</del>", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><del></html_inline>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
</emph>
|
||||
<html_inline></del></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<pre language=""haskell""><code>
|
||||
import Text.HTML.TagSoup
|
||||
|
||||
main :: IO ()
|
||||
main = print $ parseTags tags
|
||||
</code></pre>
|
||||
okay", @"<document>
|
||||
<html_block><pre language=""haskell""><code>
|
||||
import Text.HTML.TagSoup
|
||||
|
||||
main :: IO ()
|
||||
main = print $ parseTags tags
|
||||
</code></pre></html_block>
|
||||
<paragraph>
|
||||
<text>okay</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<script type=""text/javascript"">
|
||||
// JavaScript example
|
||||
|
||||
document.getElementById(""demo"").innerHTML = ""Hello JavaScript!"";
|
||||
</script>
|
||||
okay", @"<document>
|
||||
<html_block><script type=""text/javascript"">
|
||||
// JavaScript example
|
||||
|
||||
document.getElementById(""demo"").innerHTML = ""Hello JavaScript!"";
|
||||
</script></html_block>
|
||||
<paragraph>
|
||||
<text>okay</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<textarea>
|
||||
|
||||
*foo*
|
||||
|
||||
_bar_
|
||||
|
||||
</textarea>", @"<document>
|
||||
<html_block><textarea>
|
||||
|
||||
*foo*
|
||||
|
||||
_bar_
|
||||
|
||||
</textarea></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<style
|
||||
type=""text/css"">
|
||||
h1 {color:red;}
|
||||
|
||||
p {color:blue;}
|
||||
</style>
|
||||
okay",@"<document>
|
||||
<html_block><style
|
||||
type=""text/css"">
|
||||
h1 {color:red;}
|
||||
|
||||
p {color:blue;}
|
||||
</style></html_block>
|
||||
<paragraph>
|
||||
<text>okay</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<style
|
||||
type=""text/css"">
|
||||
|
||||
foo", @"<document>
|
||||
<html_block><style
|
||||
type=""text/css"">
|
||||
|
||||
foo</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"> <div>
|
||||
> foo
|
||||
|
||||
bar", @"<document>
|
||||
<block_quote>
|
||||
<html_block><div>
|
||||
foo</html_block>
|
||||
</block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- <div>
|
||||
- foo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<html_block><div></html_block>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"<style>p{color:red;}</style>
|
||||
*foo*", @"<document>
|
||||
<html_block><style>p{color:red;}</style></html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<!-- foo -->*bar*
|
||||
*baz*", @"<document>
|
||||
<html_block><!-- foo -->*bar*</html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>baz</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<script>
|
||||
foo
|
||||
</script>1. *bar*", @"<document>
|
||||
<html_block><script>
|
||||
foo
|
||||
</script>1. *bar*</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<!-- Foo
|
||||
|
||||
bar
|
||||
baz -->
|
||||
okay", @"<document>
|
||||
<html_block><!-- Foo
|
||||
|
||||
bar
|
||||
baz --></html_block>
|
||||
<paragraph>
|
||||
<text>okay</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<?php
|
||||
|
||||
echo '>';
|
||||
|
||||
?>
|
||||
okay", @"<document>
|
||||
<html_block><?php
|
||||
|
||||
echo '>';
|
||||
|
||||
?></html_block>
|
||||
<paragraph>
|
||||
<text>okay</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<!DOCTYPE html>", @"<document>
|
||||
<html_block><!DOCTYPE html></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<![CDATA[
|
||||
function matchwo(a,b)
|
||||
{
|
||||
if (a < b && a < 0) then {
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
]]>
|
||||
okay", @"<document>
|
||||
<html_block><![CDATA[
|
||||
function matchwo(a,b)
|
||||
{
|
||||
if (a < b && a < 0) then {
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
]]></html_block>
|
||||
<paragraph>
|
||||
<text>okay</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" <!-- foo -->
|
||||
|
||||
<!-- foo -->", @"<document>
|
||||
<html_block> <!-- foo --></html_block>
|
||||
<code_block><!-- foo -->
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" <div>
|
||||
|
||||
<div>", @"<document>
|
||||
<html_block> <div></html_block>
|
||||
<code_block><div>
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
<div>
|
||||
bar
|
||||
</div>", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
<html_block><div>
|
||||
bar
|
||||
</div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div>
|
||||
bar
|
||||
</div>
|
||||
*foo*", @"<document>
|
||||
<html_block><div>
|
||||
bar
|
||||
</div>
|
||||
*foo*</html_block>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
<a href=""bar"">
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<html_inline><a href=""bar""></html_inline>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<div>
|
||||
|
||||
*Emphasized* text.
|
||||
|
||||
</div>", @"<document>
|
||||
<html_block><div></html_block>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>Emphasized</text>
|
||||
</emph>
|
||||
<text> text.</text>
|
||||
</paragraph>
|
||||
<html_block></div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<div>
|
||||
*Emphasized* text.
|
||||
</div>", @"<document>
|
||||
<html_block><div>
|
||||
*Emphasized* text.
|
||||
</div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<table>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
Hi
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>", @"<document>
|
||||
<html_block><table></html_block>
|
||||
<html_block><tr></html_block>
|
||||
<html_block><td>
|
||||
Hi
|
||||
</td></html_block>
|
||||
<html_block></tr></html_block>
|
||||
<html_block></table></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"<table>
|
||||
|
||||
<tr>
|
||||
|
||||
<td>
|
||||
Hi
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
</table>", @"<document>
|
||||
<html_block><table></html_block>
|
||||
<html_block> <tr></html_block>
|
||||
<code_block><td>
|
||||
Hi
|
||||
</td>
|
||||
</code_block>
|
||||
<html_block> </tr></html_block>
|
||||
<html_block></table></html_block>
|
||||
</document>")]
|
||||
public void Parse_HtmlBlock(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
168
Radzen.Blazor.Tests/Markdown/HtmlInlineTests.cs
Normal file
168
Radzen.Blazor.Tests/Markdown/HtmlInlineTests.cs
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class HtmlInlineTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"<a><bab><c2c>", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><a></html_inline>
|
||||
<html_inline><bab></html_inline>
|
||||
<html_inline><c2c></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a/><b2/>", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><a/></html_inline>
|
||||
<html_inline><b2/></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a /><b2
|
||||
data=""foo"" >", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><a /></html_inline>
|
||||
<html_inline><b2
|
||||
data=""foo"" ></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a foo=""bar"" bam = 'baz <em>""</em>'
|
||||
_boolean zoop:33=zoop:33 />", @"<document>
|
||||
<paragraph>
|
||||
<html_inline><a foo=""bar"" bam = 'baz <em>""</em>'
|
||||
_boolean zoop:33=zoop:33 /></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"Foo <responsive-image src=""foo.jpg"" />", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo </text>
|
||||
<html_inline><responsive-image src=""foo.jpg"" /></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("<33> <__>", @"<document>
|
||||
<paragraph>
|
||||
<text><33> <</text>
|
||||
<text>__</text>
|
||||
<text>></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a h*#ref=""hi"">", @"<document>
|
||||
<paragraph>
|
||||
<text><a h</text>
|
||||
<text>*</text>
|
||||
<text>#ref=""hi""></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<a href='bar'title=title>", @"<document>
|
||||
<paragraph>
|
||||
<text><a href='bar'title=title></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"</a></foo >", @"<document>
|
||||
<paragraph>
|
||||
<html_inline></a></html_inline>
|
||||
<html_inline></foo ></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"</a href=""foo"">", @"<document>
|
||||
<paragraph>
|
||||
<text></a href=""foo""></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <!-- this is a --
|
||||
comment - with hyphens -->", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><!-- this is a --
|
||||
comment - with hyphens --></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <!--> foo -->
|
||||
|
||||
foo <!---> foo -->
|
||||
", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><!--></html_inline>
|
||||
<text> foo --></text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><!---></html_inline>
|
||||
<text> foo --></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <?php echo $a; ?>", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><?php echo $a; ?></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <!ELEMENT br EMPTY>", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><!ELEMENT br EMPTY></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <![CDATA[>&<]]>", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><![CDATA[>&<]]></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <a href=""ö"">", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><a href=""&ouml;""></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <a href=""\*"">", @"<document>
|
||||
<paragraph>
|
||||
<text>foo </text>
|
||||
<html_inline><a href=""\*""></html_inline>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo <a href=""\"""">", @"<document>
|
||||
<paragraph>
|
||||
<text>foo <a href=""</text>
|
||||
<text>""</text>
|
||||
<text>""></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_Html(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("***foo bar***", @"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<strong>
|
||||
<text>foo bar</text>
|
||||
</strong>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("___foo bar___", @"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<strong>
|
||||
<text>foo bar</text>
|
||||
</strong>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_BoldAndItalic_ShouldNotThrowException(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
85
Radzen.Blazor.Tests/Markdown/ImageTests.cs
Normal file
85
Radzen.Blazor.Tests/Markdown/ImageTests.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class ImageTests
|
||||
{
|
||||
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"", @"<document>
|
||||
<paragraph>
|
||||
<image destination=""/url"" title=""title"">
|
||||
<text>foo</text>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"](/url2)", @"<document>
|
||||
<paragraph>
|
||||
<image destination=""/url2"" title="""">
|
||||
<text>foo </text>
|
||||
<image destination=""/url"" title="""">
|
||||
<text>bar</text>
|
||||
</image>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"](/url2)", @"<document>
|
||||
<paragraph>
|
||||
<image destination=""/url2"" title="""">
|
||||
<text>foo </text>
|
||||
<link destination=""/url"" title="""">
|
||||
<text>bar</text>
|
||||
</link>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"", @"<document>
|
||||
<paragraph>
|
||||
<image destination=""train.jpg"" title="""">
|
||||
<text>foo</text>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"My ", @"<document>
|
||||
<paragraph>
|
||||
<text>My </text>
|
||||
<image destination=""/path/to/train.jpg"" title=""title"">
|
||||
<text>foo bar</text>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"", @"<document>
|
||||
<paragraph>
|
||||
<image destination=""url"" title="""">
|
||||
<text>foo</text>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"", @"<document>
|
||||
<paragraph>
|
||||
<image destination=""/url"" title="""" />
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"__Applications__ ", @"<document>
|
||||
<paragraph>
|
||||
<strong>
|
||||
<text>Applications</text>
|
||||
</strong>
|
||||
<text> </text>
|
||||
<image destination=""/assets/img/macOS-drag-and-drop.png"" title="""">
|
||||
<text>macOS DMG</text>
|
||||
</image>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_BasicImages_ReturnsImageElement(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
145
Radzen.Blazor.Tests/Markdown/IndentedCodeBlockTests.cs
Normal file
145
Radzen.Blazor.Tests/Markdown/IndentedCodeBlockTests.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class IndentedCodeBlockTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@" a simple
|
||||
indented code block
|
||||
", @"<document>
|
||||
<code_block>a simple
|
||||
indented code block
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" - foo
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(
|
||||
@"
|
||||
1. foo
|
||||
|
||||
- bar", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" <a/>
|
||||
*hi*
|
||||
|
||||
- one", @"<document>
|
||||
<code_block><a/>
|
||||
*hi*
|
||||
|
||||
- one
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" chunk1
|
||||
|
||||
chunk2
|
||||
|
||||
|
||||
|
||||
chunk3", @"<document>
|
||||
<code_block>chunk1
|
||||
|
||||
chunk2
|
||||
|
||||
|
||||
|
||||
chunk3
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" chunk1
|
||||
|
||||
chunk2", @"<document>
|
||||
<code_block>chunk1
|
||||
|
||||
chunk2
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
bar", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" foo
|
||||
bar", @"<document>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"# Heading
|
||||
foo
|
||||
Heading
|
||||
------
|
||||
foo
|
||||
----", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>Heading</text>
|
||||
</heading>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
<heading level=""2"">
|
||||
<text>Heading</text>
|
||||
</heading>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@" foo
|
||||
bar", @"<document>
|
||||
<code_block> foo
|
||||
bar
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"
|
||||
|
||||
foo
|
||||
", @"<document>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" foo ", @"<document>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
</document>")]
|
||||
public void Parse_IndentedCodeBlock(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
852
Radzen.Blazor.Tests/Markdown/LinkTests.cs
Normal file
852
Radzen.Blazor.Tests/Markdown/LinkTests.cs
Normal file
@@ -0,0 +1,852 @@
|
||||
using System.Runtime.InteropServices;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class LinkTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("[link](/uri \"title\")",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<link destination=""/uri"" title=""title"">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[link](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[](./target.md)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""./target.md"" title="""" />
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[link]()", @"<document>
|
||||
<paragraph>
|
||||
<link destination="""" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[link](<>)", @"<document>
|
||||
<paragraph>
|
||||
<link destination="""" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[]()", @"<document>
|
||||
<paragraph>
|
||||
<link destination="""" title="""" />
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_BasicLinks_ReturnsLinkNode(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("[link](/my uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>](/my uri)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("[link](</my uri>)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/my uri"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_LinkDestinationWithSpaces(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](foo
|
||||
bar)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>](foo</text>
|
||||
<softbreak />
|
||||
<text>bar)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
|
||||
public void Parse_LinkDestinationWithNewLines(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[a](<b)c>)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""b)c"" title="""">
|
||||
<text>a</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_LinkDestinationWithCloseParenthesis(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](<foo\>)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>](<foo>)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[a](<b)c
|
||||
[a](<b)c>
|
||||
[a](<b>c)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>a</text>
|
||||
<text>](<b)c</text>
|
||||
<softbreak />
|
||||
<text>[</text>
|
||||
<text>a</text>
|
||||
<text>](<b)c></text>
|
||||
<softbreak />
|
||||
<text>[</text>
|
||||
<text>a</text>
|
||||
<text>](</text>
|
||||
<html_inline><b></html_inline>
|
||||
<text>c)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_LinkDestinationUnclosedPointyBracket(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](\(foo\))", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""(foo)"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](foo\)\:)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""foo):"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](foo\bar)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""foo\bar"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_Escapes(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](foo(and(bar)))", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""foo(and(bar))"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](foo(and(bar))", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>](foo(and(bar))</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](foo\(and\(bar\))", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""foo(and(bar)"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](<foo(and(bar)>)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""foo(and(bar)"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_BallancedParenthesisInLinkDestination(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](#fragment)
|
||||
[link](https://example.com#fragment)
|
||||
[link](https://example.com?foo=3#frag)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""#fragment"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
<softbreak />
|
||||
<link destination=""https://example.com#fragment"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
<softbreak />
|
||||
<link destination=""https://example.com?foo=3#frag"" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_FragmentAndQueryStringInLinkDestination(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](""title"")", @"<document>
|
||||
<paragraph>
|
||||
<link destination="""title""" title="""">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_QuotesInDestination(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link](/url ""title"")
|
||||
[link](/url 'title')
|
||||
[link](/url (title))", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title=""title"">
|
||||
<text>link</text>
|
||||
</link>
|
||||
<softbreak />
|
||||
<link destination=""/url"" title=""title"">
|
||||
<text>link</text>
|
||||
</link>
|
||||
<softbreak />
|
||||
<link destination=""/url"" title=""title"">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](/url ""title ""and"" title"")", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>](/url ""title ""and"" title"")</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link](/url 'title ""and"" title')", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title=""title "and" title"">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_Title(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link]( /url
|
||||
""title"" )", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title=""title"">
|
||||
<text>link</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link] (/uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>] (/uri)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_SpacesInLink(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link [foo [bar]]](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>link </text>
|
||||
<text>[</text>
|
||||
<text>foo </text>
|
||||
<text>[</text>
|
||||
<text>bar</text>
|
||||
<text>]</text>
|
||||
<text>]</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link] bar](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link</text>
|
||||
<text>] bar](/uri)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link [bar](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>link </text>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>bar</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[link \[bar](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>link </text>
|
||||
<text>[</text>
|
||||
<text>bar</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_BracketsInText(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[link *foo **bar** `#`*](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>link </text>
|
||||
<emph>
|
||||
<text>foo </text>
|
||||
<strong>
|
||||
<text>bar</text>
|
||||
</strong>
|
||||
<text> </text>
|
||||
<code>#</code>
|
||||
</emph>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[](url)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""url"" title="""">
|
||||
<image destination=""img"" title="""">
|
||||
<text>alt</text>
|
||||
</image>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
|
||||
public void Parse_LinkTextIsInlineContent(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[foo [bar](/uri)](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo </text>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>bar</text>
|
||||
</link>
|
||||
<text>](/uri)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo *[bar [baz](/uri)](/uri)*](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo </text>
|
||||
<emph>
|
||||
<text>[</text>
|
||||
<text>bar </text>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>baz</text>
|
||||
</link>
|
||||
<text>](/uri)</text>
|
||||
</emph>
|
||||
<text>](/uri)</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_NestedLinks(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"*[foo*](/uri)", @"<document>
|
||||
<paragraph>
|
||||
<text>*</text>
|
||||
<link destination=""/uri"" title="""">
|
||||
<text>foo</text>
|
||||
<text>*</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo *bar](baz*)", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""baz*"" title="""">
|
||||
<text>foo </text>
|
||||
<text>*</text>
|
||||
<text>bar</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"*foo [bar* baz]", @"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>foo </text>
|
||||
<text>[</text>
|
||||
<text>bar</text>
|
||||
</emph>
|
||||
<text> baz</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo`](/uri)`", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<code>](/uri)</code>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_Precedence(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"<http://foo.bar.baz>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""http://foo.bar.baz"" title="""">
|
||||
<text>http://foo.bar.baz</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<https://foo.bar.baz/test?q=hello&id=22&boolean>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""https://foo.bar.baz/test?q=hello&id=22&boolean"" title="""">
|
||||
<text>https://foo.bar.baz/test?q=hello&id=22&boolean</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<irc://foo.bar:2233/baz>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""irc://foo.bar:2233/baz"" title="""">
|
||||
<text>irc://foo.bar:2233/baz</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<MAILTO:FOO@BAR.BAZ>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""MAILTO:FOO@BAR.BAZ"" title="""">
|
||||
<text>MAILTO:FOO@BAR.BAZ</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<https://foo.bar/baz bim>", @"<document>
|
||||
<paragraph>
|
||||
<text><https://foo.bar/baz bim></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<https://example.com/\[\>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""https://example.com/\[\"" title="""">
|
||||
<text>https://example.com/\[\</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<foo@bar.example.com>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""mailto:foo@bar.example.com"" title="""">
|
||||
<text>foo@bar.example.com</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<foo+special@Bar.baz-bar0.com>", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""mailto:foo+special@Bar.baz-bar0.com"" title="""">
|
||||
<text>foo+special@Bar.baz-bar0.com</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<foo\+@bar.example.com>", @"<document>
|
||||
<paragraph>
|
||||
<text><foo+@bar.example.com></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<>", @"<document>
|
||||
<paragraph>
|
||||
<text><></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"< https://foo.bar >", @"<document>
|
||||
<paragraph>
|
||||
<text>< https://foo.bar ></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<m:abc>", @"<document>
|
||||
<paragraph>
|
||||
<text><m:abc></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"<foo.bar.baz>", @"<document>
|
||||
<paragraph>
|
||||
<text><foo.bar.baz></text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"https://example.com", @"<document>
|
||||
<paragraph>
|
||||
<text>https://example.com</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"foo@bar.example.com", @"<document>
|
||||
<paragraph>
|
||||
<text>foo@bar.example.com</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_AutoLink(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"[foo]: /url ""title""
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title=""title"">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" [foo]:
|
||||
/url
|
||||
'the title'
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title=""the title"">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[Foo*bar\]]:my_(url) 'title (with parens)'
|
||||
|
||||
[Foo*bar\]]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""my_(url)"" title=""title (with parens)"">
|
||||
<text>Foo</text>
|
||||
<text>*</text>
|
||||
<text>bar</text>
|
||||
<text>]</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[Foo bar]:
|
||||
<my url>
|
||||
'title'
|
||||
|
||||
[Foo bar]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""my url"" title=""title"">
|
||||
<text>Foo bar</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url '
|
||||
title
|
||||
line1
|
||||
line2
|
||||
'
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title=""
title
line1
line2
"">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url 'title
|
||||
|
||||
with blank line'
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]: /url 'title</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>with blank line'</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]:
|
||||
/url
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]:
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]:</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: <>
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<link destination="""" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: <bar>(baz)
|
||||
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]: </text>
|
||||
<html_inline><bar></html_inline>
|
||||
<text>(baz)</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url\bar\*baz ""foo\""bar\baz""
|
||||
|
||||
[foo]
|
||||
", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url\bar*baz"" title=""foo\"bar\baz"">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]
|
||||
|
||||
[foo]: url", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""url"" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]
|
||||
|
||||
[foo]: first
|
||||
[foo]: second", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""first"" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[FOO]: /url
|
||||
|
||||
[Foo]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title="""">
|
||||
<text>Foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[ΑΓΩ]: /φου
|
||||
|
||||
[αγω]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/φου"" title="""">
|
||||
<text>αγω</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url", @"<document />")]
|
||||
[InlineData(@"[
|
||||
foo
|
||||
]: /url
|
||||
bar", @"<document>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url ""title"" ok", @"<document>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]: /url ""title"" ok</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url
|
||||
""title"" ok", @"<document>
|
||||
<paragraph>
|
||||
<text>""title"" ok</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" [foo]: /url ""title""
|
||||
|
||||
[foo]", @"<document>
|
||||
<code_block>[foo]: /url ""title""
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"```
|
||||
[foo]: /url
|
||||
```
|
||||
|
||||
[foo]", @"<document>
|
||||
<code_block>[foo]: /url
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>foo</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
[bar]: /baz
|
||||
|
||||
[bar]", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>[</text>
|
||||
<text>bar</text>
|
||||
<text>]: /baz</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>[</text>
|
||||
<text>bar</text>
|
||||
<text>]</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"# [Foo]
|
||||
[foo]: /url
|
||||
> bar", @"<document>
|
||||
<heading level=""1"">
|
||||
<link destination=""/url"" title="""">
|
||||
<text>Foo</text>
|
||||
</link>
|
||||
</heading>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url
|
||||
bar
|
||||
===
|
||||
[foo]", @"<document>
|
||||
<heading level=""1"">
|
||||
<text>bar</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /url
|
||||
===
|
||||
[foo]", @"<document>
|
||||
<paragraph>
|
||||
<text>===</text>
|
||||
<softbreak />
|
||||
<link destination=""/url"" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]: /foo-url ""foo""
|
||||
[bar]: /bar-url
|
||||
""bar""
|
||||
[baz]: /baz-url
|
||||
|
||||
[foo],
|
||||
[bar],
|
||||
[baz]", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/foo-url"" title=""foo"">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
<text>,</text>
|
||||
<softbreak />
|
||||
<link destination=""/bar-url"" title=""bar"">
|
||||
<text>bar</text>
|
||||
</link>
|
||||
<text>,</text>
|
||||
<softbreak />
|
||||
<link destination=""/baz-url"" title="""">
|
||||
<text>baz</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"[foo]
|
||||
|
||||
> [foo]: /url
|
||||
", @"<document>
|
||||
<paragraph>
|
||||
<link destination=""/url"" title="""">
|
||||
<text>foo</text>
|
||||
</link>
|
||||
</paragraph>
|
||||
<block_quote />
|
||||
</document>")]
|
||||
public void Parse_LinkReference(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
880
Radzen.Blazor.Tests/Markdown/ListItemTests.cs
Normal file
880
Radzen.Blazor.Tests/Markdown/ListItemTests.cs
Normal file
@@ -0,0 +1,880 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class ListItemTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>A paragraph</text>
|
||||
<softbreak />
|
||||
<text>with two lines.</text>
|
||||
</paragraph>
|
||||
<code_block>indented code
|
||||
</code_block>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>A block quote.</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- one
|
||||
|
||||
two", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>one</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<paragraph>
|
||||
<text>two</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- one
|
||||
|
||||
two", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>one</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>two</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" - one
|
||||
|
||||
two", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>one</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<code_block> two
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" - one
|
||||
|
||||
two", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>one</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>two</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" > > 1. one
|
||||
>>
|
||||
>> two
|
||||
", @"<document>
|
||||
<block_quote>
|
||||
<block_quote>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>one</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>two</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</block_quote>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@">>- one
|
||||
>>
|
||||
> > two
|
||||
", @"<document>
|
||||
<block_quote>
|
||||
<block_quote>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>one</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<paragraph>
|
||||
<text>two</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"-one
|
||||
|
||||
2.two
|
||||
", @"<document>
|
||||
<paragraph>
|
||||
<text>-one</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>2.two</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. foo
|
||||
|
||||
```
|
||||
bar
|
||||
```
|
||||
|
||||
baz
|
||||
|
||||
> bam", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bam</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- Foo
|
||||
|
||||
bar
|
||||
|
||||
|
||||
baz", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
<code_block>bar
|
||||
|
||||
|
||||
baz
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"123456789. ok", @"<document>
|
||||
<list type=""ordered"" start=""123456789"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>ok</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1234567890. not ok", @"<document>
|
||||
<paragraph>
|
||||
<text>1234567890. not ok</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"0. ok", @"<document>
|
||||
<list type=""ordered"" start=""0"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>ok</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"003. ok", @"<document>
|
||||
<list type=""ordered"" start=""3"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>ok</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"-1. not ok", @"<document>
|
||||
<paragraph>
|
||||
<text>-1. not ok</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" 10. foo
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""ordered"" start=""10"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. indented code
|
||||
|
||||
paragraph
|
||||
|
||||
more code", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<code_block>indented code
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>paragraph</text>
|
||||
</paragraph>
|
||||
<code_block>more code
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- indented code
|
||||
|
||||
paragraph
|
||||
|
||||
more code", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<code_block>indented code
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>paragraph</text>
|
||||
</paragraph>
|
||||
<code_block>more code
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. indented code
|
||||
|
||||
paragraph
|
||||
|
||||
more code", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<code_block> indented code
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>paragraph</text>
|
||||
</paragraph>
|
||||
<code_block>more code
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"-
|
||||
foo
|
||||
-
|
||||
```
|
||||
bar
|
||||
```
|
||||
-
|
||||
baz", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
</item>
|
||||
<item>
|
||||
<code_block>baz
|
||||
</code_block>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1.
|
||||
foo", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"-
|
||||
foo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"-
|
||||
|
||||
foo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item />
|
||||
</list>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
-
|
||||
- bar", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item />
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
-
|
||||
- bar", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item />
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. foo
|
||||
2.
|
||||
3. bar", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item />
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"*", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item />
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"foo
|
||||
*
|
||||
|
||||
foo
|
||||
1.", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>*</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>1.</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" 1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>A paragraph</text>
|
||||
<softbreak />
|
||||
<text>with two lines.</text>
|
||||
</paragraph>
|
||||
<code_block>indented code
|
||||
</code_block>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>A block quote.</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" 1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>A paragraph</text>
|
||||
<softbreak />
|
||||
<text>with two lines.</text>
|
||||
</paragraph>
|
||||
<code_block>indented code
|
||||
</code_block>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>A block quote.</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" 1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>A paragraph</text>
|
||||
<softbreak />
|
||||
<text>with two lines.</text>
|
||||
</paragraph>
|
||||
<code_block>indented code
|
||||
</code_block>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>A block quote.</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@" 1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.", @"<document>
|
||||
<code_block>1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.
|
||||
</code_block>
|
||||
</document>")]
|
||||
public void Parse_ListItem(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@" 1. A paragraph
|
||||
with two lines.
|
||||
|
||||
indented code
|
||||
|
||||
> A block quote.", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>A paragraph</text>
|
||||
<softbreak />
|
||||
<text>with two lines.</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>indented code</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<code_block> > A block quote.
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@" 1. A paragraph
|
||||
with two lines.", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>A paragraph</text>
|
||||
<softbreak />
|
||||
<text>with two lines.</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"> 1. > Blockquote
|
||||
continued here.", @"<document>
|
||||
<block_quote>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>Blockquote</text>
|
||||
<softbreak />
|
||||
<text>continued here.</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"> 1. > Blockquote
|
||||
> continued here.", @"<document>
|
||||
<block_quote>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>Blockquote</text>
|
||||
<softbreak />
|
||||
<text>continued here.</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
</list>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
public void Parse_ListItem_WithLazyContinuation(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"- foo
|
||||
- bar
|
||||
- baz
|
||||
- boo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>boo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
- bar
|
||||
- baz
|
||||
- boo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>boo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. foo
|
||||
1. bar
|
||||
1. baz
|
||||
1. boo", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>boo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"
|
||||
1. foo
|
||||
1. bar
|
||||
1. baz
|
||||
1. boo", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>boo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"10) foo
|
||||
- bar", @"<document>
|
||||
<list type=""ordered"" start=""10"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"
|
||||
10) foo
|
||||
- bar", @"<document>
|
||||
<list type=""ordered"" start=""10"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- - foo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. - foo", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. 1. foo", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- 1. foo", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. - 2. foo", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<list type=""ordered"" start=""2"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- # Foo
|
||||
- Bar
|
||||
---
|
||||
baz", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<heading level=""1"">
|
||||
<text>Foo</text>
|
||||
</heading>
|
||||
</item>
|
||||
<item>
|
||||
<heading level=""2"">
|
||||
<text>Bar</text>
|
||||
</heading>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
public void Parse_ListItem_WithNesting(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
693
Radzen.Blazor.Tests/Markdown/ListTests.cs
Normal file
693
Radzen.Blazor.Tests/Markdown/ListTests.cs
Normal file
@@ -0,0 +1,693 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class ListTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"- foo
|
||||
- bar
|
||||
+ baz", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. foo
|
||||
2. bar
|
||||
3) baz", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<list type=""ordered"" start=""3"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
- bar
|
||||
- baz", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
public void Parse_List(string markdown, string expected)
|
||||
{
|
||||
var actual = ToXml(markdown);
|
||||
|
||||
Assert.Equal(expected, actual);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"The number of windows in my house is
|
||||
14. The number of doors is 6.", @"<document>
|
||||
<paragraph>
|
||||
<text>The number of windows in my house is</text>
|
||||
<softbreak />
|
||||
<text>14. The number of doors is 6.</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"The number of windows in my house is
|
||||
1. The number of doors is 6.", @"<document>
|
||||
<paragraph>
|
||||
<text>The number of windows in my house is</text>
|
||||
</paragraph>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>The number of doors is 6.</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
public void Parse_OnlyNumberedListsThatStartWithOneCanInterruptParagraphs(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"- foo
|
||||
|
||||
- bar
|
||||
|
||||
|
||||
- baz", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
- bar
|
||||
- baz
|
||||
|
||||
|
||||
bim
|
||||
", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bim</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
|
||||
- c", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"* a
|
||||
*
|
||||
|
||||
* c", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item />
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
|
||||
c
|
||||
- d", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
|
||||
[ref]: /url
|
||||
- d", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- ```
|
||||
b
|
||||
|
||||
|
||||
```
|
||||
- c", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<code_block>b
|
||||
|
||||
|
||||
</code_block>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
|
||||
c
|
||||
- d", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"* a
|
||||
> b
|
||||
>
|
||||
* c", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
> b
|
||||
```
|
||||
c
|
||||
```
|
||||
- d
|
||||
", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
<code_block>c
|
||||
</code_block>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. ```
|
||||
foo
|
||||
```
|
||||
|
||||
bar", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<code_block>foo
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"* foo
|
||||
* bar
|
||||
|
||||
baz", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
- c
|
||||
|
||||
- d
|
||||
- e
|
||||
- f", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
</paragraph>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>e</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>f</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
public void Parse_TightAndLooseLists(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"- foo
|
||||
- bar
|
||||
|
||||
<!-- -->
|
||||
|
||||
- baz
|
||||
- bim", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<html_block><!-- --></html_block>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bim</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
|
||||
notcode
|
||||
|
||||
- foo
|
||||
|
||||
<!-- -->
|
||||
|
||||
code", @"<document>
|
||||
<list type=""bullet"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>notcode</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<html_block><!-- --></html_block>
|
||||
<code_block>code
|
||||
</code_block>
|
||||
</document>")]
|
||||
public void Parse_List_Separators(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
- c
|
||||
- d
|
||||
- e
|
||||
- f
|
||||
- g", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>e</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>f</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>g</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. a
|
||||
|
||||
2. b
|
||||
|
||||
3. c
|
||||
", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- a
|
||||
- b
|
||||
- c
|
||||
- d
|
||||
- e", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>d</text>
|
||||
<softbreak />
|
||||
<text>- e</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"1. a
|
||||
|
||||
2. b
|
||||
|
||||
3. c", @"<document>
|
||||
<list type=""ordered"" start=""1"" tight=""false"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<code_block>3. c
|
||||
</code_block>
|
||||
</document>")]
|
||||
public void Parse_List_Identation(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_BasicNestedLists()
|
||||
{
|
||||
Assert.Equal(@"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>b</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>c</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>", ToXml(@"
|
||||
- a
|
||||
- b
|
||||
- c"));
|
||||
}
|
||||
}
|
||||
109
Radzen.Blazor.Tests/Markdown/ParagraphTests.cs
Normal file
109
Radzen.Blazor.Tests/Markdown/ParagraphTests.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class ParagraphTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
[Fact]
|
||||
public void Parse_BasicParagraph()
|
||||
{
|
||||
Assert.Equal(@"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</document>", ToXml(@"foo"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"aaa
|
||||
|
||||
bbb", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"aaa
|
||||
bbb
|
||||
|
||||
ccc
|
||||
ddd", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
<softbreak />
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>ccc</text>
|
||||
<softbreak />
|
||||
<text>ddd</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"aaa
|
||||
|
||||
|
||||
bbb
|
||||
", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" aaa
|
||||
bbb", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
<softbreak />
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"aaa
|
||||
bbb
|
||||
ccc", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
<softbreak />
|
||||
<text>bbb</text>
|
||||
<softbreak />
|
||||
<text>ccc</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" aaa
|
||||
bbb", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
<softbreak />
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" aaa
|
||||
bbb", @"<document>
|
||||
<code_block>aaa
|
||||
</code_block>
|
||||
<paragraph>
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"aaa
|
||||
bbb ", @"<document>
|
||||
<paragraph>
|
||||
<text>aaa</text>
|
||||
<linebreak />
|
||||
<text>bbb</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_Paragraph(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
41
Radzen.Blazor.Tests/Markdown/SoftLineBreakTests.cs
Normal file
41
Radzen.Blazor.Tests/Markdown/SoftLineBreakTests.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class SoftLineBreakTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"foo
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_SoftLineBreak(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"foo
|
||||
baz", @"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<softbreak />
|
||||
<text>baz</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_SoftLine_RemovesSpacesAtEndAndStartOfLine(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
135
Radzen.Blazor.Tests/Markdown/StrongTests.cs
Normal file
135
Radzen.Blazor.Tests/Markdown/StrongTests.cs
Normal file
@@ -0,0 +1,135 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class StrongTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("**foo bar**",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<strong>
|
||||
<text>foo bar</text>
|
||||
</strong>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("** foo bar**",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>**</text>
|
||||
<text> foo bar</text>
|
||||
<text>**</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("a**\"foo\"**",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
<text>**</text>
|
||||
<text>""foo""</text>
|
||||
<text>**</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("foo**bar**",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<strong>
|
||||
<text>bar</text>
|
||||
</strong>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("__foo bar__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<strong>
|
||||
<text>foo bar</text>
|
||||
</strong>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("__ foo bar__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>__</text>
|
||||
<text> foo bar</text>
|
||||
<text>__</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("__\nfoo bar__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>__</text>
|
||||
<softbreak />
|
||||
<text>foo bar</text>
|
||||
<text>__</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("a__\"foo\"__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>a</text>
|
||||
<text>__</text>
|
||||
<text>""foo""</text>
|
||||
<text>__</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("foo__bar__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
<text>__</text>
|
||||
<text>bar</text>
|
||||
<text>__</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("5__6__78",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>5</text>
|
||||
<text>__</text>
|
||||
<text>6</text>
|
||||
<text>__</text>
|
||||
<text>78</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("пристаням__стремятся__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>пристаням</text>
|
||||
<text>__</text>
|
||||
<text>стремятся</text>
|
||||
<text>__</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("__foo, __bar__, baz__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<strong>
|
||||
<text>foo, </text>
|
||||
<strong>
|
||||
<text>bar</text>
|
||||
</strong>
|
||||
<text>, baz</text>
|
||||
</strong>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData("foo-__(bar)__",
|
||||
@"<document>
|
||||
<paragraph>
|
||||
<text>foo-</text>
|
||||
<strong>
|
||||
<text>(bar)</text>
|
||||
</strong>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_StrongEmphasisRules_AdheresToCommonMarkSpec(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
414
Radzen.Blazor.Tests/Markdown/TableTests.cs
Normal file
414
Radzen.Blazor.Tests/Markdown/TableTests.cs
Normal file
@@ -0,0 +1,414 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class TableTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Parse_BasicTable()
|
||||
{
|
||||
Assert.Equal(
|
||||
@"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>foo</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>bim</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
</document>",
|
||||
ToXml(@"
|
||||
foo|bar
|
||||
--|--
|
||||
baz|bim"));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"| foo | bar |
|
||||
| --- | --- |
|
||||
| baz | bim |", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>foo</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>bim</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
</document>")]
|
||||
[InlineData(@"| f\|oo |
|
||||
| ------ |
|
||||
| b `\|` az |
|
||||
| b **\|** im |", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>f|oo</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>b </text>
|
||||
<code>|</code>
|
||||
<text> az</text>
|
||||
</cell>
|
||||
</row>
|
||||
<row>
|
||||
<cell>
|
||||
<text>b </text>
|
||||
<strong>
|
||||
<text>|</text>
|
||||
</strong>
|
||||
<text> im</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | defghi |
|
||||
:-: | -----------:
|
||||
bar | baz", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell align=""center"">
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell align=""right"">
|
||||
<text>defghi</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell align=""center"">
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell align=""right"">
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
</document>")]
|
||||
|
||||
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
bar", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell />
|
||||
</row>
|
||||
</table>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
c:\\foo", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>c:</text>
|
||||
<text>\</text>
|
||||
<text>foo</text>
|
||||
</cell>
|
||||
<cell />
|
||||
</row>
|
||||
</table>
|
||||
</document>")]
|
||||
public void Parse_Table(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
| bar | baz |
|
||||
|
||||
boo", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
<paragraph>
|
||||
<text>boo</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"| foo |
|
||||
| --- |
|
||||
# bar", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>foo</text>
|
||||
</cell>
|
||||
</header>
|
||||
</table>
|
||||
<heading level=""1"">
|
||||
<text>bar</text>
|
||||
</heading>
|
||||
</document>")]
|
||||
[InlineData(@"| foo |
|
||||
| --- |
|
||||
- bar", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>foo</text>
|
||||
</cell>
|
||||
</header>
|
||||
</table>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"| foo |
|
||||
| --- |
|
||||
1. bar", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>foo</text>
|
||||
</cell>
|
||||
</header>
|
||||
</table>
|
||||
<list type=""ordered"" start=""1"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
| bar | baz |
|
||||
> bar", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
<block_quote>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</block_quote>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
| bar | baz |
|
||||
bar", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
| bar | baz |
|
||||
```
|
||||
bar
|
||||
```", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
<code_block>bar
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
| bar | baz |
|
||||
<div>
|
||||
</div>", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
<html_block><div>
|
||||
</div></html_block>
|
||||
</document>")]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- | --- |
|
||||
| bar | baz |
|
||||
---", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>def</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
<cell>
|
||||
<text>baz</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
public void Parse_Table_AnyBlockOrEmptyLineBreaksTable(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"| abc | def |
|
||||
| --- |", @"<document>
|
||||
<paragraph>
|
||||
<text>| abc | def |</text>
|
||||
<softbreak />
|
||||
<text>| --- |</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
public void Parse_Table_ChecksHeaderAndDelimiter(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"| abc |
|
||||
| --- |
|
||||
| bar | baz |", @"<document>
|
||||
<table>
|
||||
<header>
|
||||
<cell>
|
||||
<text>abc</text>
|
||||
</cell>
|
||||
</header>
|
||||
<row>
|
||||
<cell>
|
||||
<text>bar</text>
|
||||
</cell>
|
||||
</row>
|
||||
</table>
|
||||
</document>")]
|
||||
public void Parse_Table_IgnoresExtraCells(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
162
Radzen.Blazor.Tests/Markdown/ThematicBreakTests.cs
Normal file
162
Radzen.Blazor.Tests/Markdown/ThematicBreakTests.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class ThematicBreakTests
|
||||
{
|
||||
private static string ToXml(string markdown)
|
||||
{
|
||||
var document = MarkdownParser.Parse(markdown);
|
||||
|
||||
return XmlVisitor.ToXml(document);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(@"***
|
||||
---
|
||||
___", @"<document>
|
||||
<thematic_break />
|
||||
<thematic_break />
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"--
|
||||
**
|
||||
__", @"<document>
|
||||
<paragraph>
|
||||
<text>--</text>
|
||||
<softbreak />
|
||||
<text>**</text>
|
||||
<softbreak />
|
||||
<text>__</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" ***
|
||||
***
|
||||
***", @"<document>
|
||||
<thematic_break />
|
||||
<thematic_break />
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@" ***", @"<document>
|
||||
<code_block>***
|
||||
</code_block>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
***", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
<softbreak />
|
||||
<text>***</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"_____________________________________", @"<document>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"- - -", @"<document>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@" ** * ** * ** * **", @"<document>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"- - - -", @"<document>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"- - - - ", @"<document>
|
||||
<thematic_break />
|
||||
</document>")]
|
||||
[InlineData(@"_ _ _ _ a
|
||||
|
||||
a------
|
||||
|
||||
---a---", @"<document>
|
||||
<paragraph>
|
||||
<text>_</text>
|
||||
<text> </text>
|
||||
<text>_</text>
|
||||
<text> </text>
|
||||
<text>_</text>
|
||||
<text> </text>
|
||||
<text>_</text>
|
||||
<text> a</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>a------</text>
|
||||
</paragraph>
|
||||
<paragraph>
|
||||
<text>---a---</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@" *-*", @"<document>
|
||||
<paragraph>
|
||||
<emph>
|
||||
<text>-</text>
|
||||
</emph>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"- foo
|
||||
***
|
||||
- bar", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<thematic_break />
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"Foo
|
||||
***
|
||||
bar", @"<document>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
<thematic_break />
|
||||
<paragraph>
|
||||
<text>bar</text>
|
||||
</paragraph>
|
||||
</document>")]
|
||||
[InlineData(@"* Foo
|
||||
* * *
|
||||
* Bar", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
<thematic_break />
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>Bar</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
[InlineData(@"- Foo
|
||||
- * * *", @"<document>
|
||||
<list type=""bullet"" tight=""true"">
|
||||
<item>
|
||||
<paragraph>
|
||||
<text>Foo</text>
|
||||
</paragraph>
|
||||
</item>
|
||||
<item>
|
||||
<thematic_break />
|
||||
</item>
|
||||
</list>
|
||||
</document>")]
|
||||
public void Parse_ThematicBreak(string markdown, string expected)
|
||||
{
|
||||
Assert.Equal(expected, ToXml(markdown));
|
||||
}
|
||||
}
|
||||
210
Radzen.Blazor.Tests/Markdown/XmlVisitor.cs
Normal file
210
Radzen.Blazor.Tests/Markdown/XmlVisitor.cs
Normal file
@@ -0,0 +1,210 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
||||
namespace Radzen.Blazor.Markdown.Tests;
|
||||
|
||||
public class XmlVisitor : NodeVisitorBase, IDisposable
|
||||
{
|
||||
private readonly XmlWriter writer;
|
||||
|
||||
private XmlVisitor(StringBuilder xml)
|
||||
{
|
||||
writer = XmlWriter.Create(xml, new XmlWriterSettings { OmitXmlDeclaration = true, Indent = true, IndentChars = " ", });
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
writer.Close();
|
||||
}
|
||||
|
||||
public static string ToXml(Document document)
|
||||
{
|
||||
var xml = new StringBuilder();
|
||||
|
||||
using var visitor = new XmlVisitor(xml);
|
||||
|
||||
document.Accept(visitor);
|
||||
|
||||
visitor.Close();
|
||||
|
||||
return xml.ToString()!;
|
||||
}
|
||||
|
||||
public override void VisitBlockQuote(BlockQuote blockQuote)
|
||||
{
|
||||
writer.WriteStartElement("block_quote");
|
||||
base.VisitBlockQuote(blockQuote);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitDocument(Document document)
|
||||
{
|
||||
writer.WriteStartDocument();
|
||||
writer.WriteStartElement("document");
|
||||
base.VisitDocument(document);
|
||||
writer.WriteEndElement();
|
||||
writer.WriteEndDocument();
|
||||
}
|
||||
|
||||
public override void VisitHeading(Heading heading)
|
||||
{
|
||||
writer.WriteStartElement($"heading");
|
||||
writer.WriteAttributeString("level", heading.Level.ToString());
|
||||
base.VisitHeading(heading);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitListItem(ListItem listItem)
|
||||
{
|
||||
writer.WriteStartElement("item");
|
||||
base.VisitListItem(listItem);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitParagraph(Paragraph paragraph)
|
||||
{
|
||||
writer.WriteStartElement("paragraph");
|
||||
base.VisitParagraph(paragraph);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitUnorderedList(UnorderedList unorderedList)
|
||||
{
|
||||
writer.WriteStartElement("list");
|
||||
writer.WriteAttributeString("type", "bullet");
|
||||
writer.WriteAttributeString("tight", unorderedList.Tight.ToString().ToLowerInvariant());
|
||||
base.VisitUnorderedList(unorderedList);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitText(Text text)
|
||||
{
|
||||
writer.WriteElementString("text", text.Value);
|
||||
}
|
||||
|
||||
public override void VisitOrderedList(OrderedList orderedList)
|
||||
{
|
||||
writer.WriteStartElement("list");
|
||||
writer.WriteAttributeString("type", "ordered");
|
||||
writer.WriteAttributeString("start", orderedList.Start.ToString());
|
||||
writer.WriteAttributeString("tight", orderedList.Tight.ToString().ToLowerInvariant());
|
||||
base.VisitOrderedList(orderedList);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitLink(Link link)
|
||||
{
|
||||
writer.WriteStartElement("link");
|
||||
writer.WriteAttributeString("destination", link.Destination);
|
||||
writer.WriteAttributeString("title", link.Title);
|
||||
base.VisitLink(link);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitImage(Image image)
|
||||
{
|
||||
writer.WriteStartElement("image");
|
||||
writer.WriteAttributeString("destination", image.Destination);
|
||||
writer.WriteAttributeString("title", image.Title);
|
||||
base.VisitImage(image);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitEmphasis(Emphasis emphasis)
|
||||
{
|
||||
writer.WriteStartElement("emph");
|
||||
base.VisitEmphasis(emphasis);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitStrong(Strong strong)
|
||||
{
|
||||
writer.WriteStartElement("strong");
|
||||
base.VisitStrong(strong);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitCode(Code code)
|
||||
{
|
||||
writer.WriteElementString("code", code.Value);
|
||||
}
|
||||
|
||||
public override void VisitHtmlInline(HtmlInline html)
|
||||
{
|
||||
writer.WriteElementString("html_inline", html.Value);
|
||||
}
|
||||
|
||||
public override void VisitLineBreak(LineBreak lineBreak)
|
||||
{
|
||||
writer.WriteElementString("linebreak", string.Empty);
|
||||
}
|
||||
|
||||
public override void VisitSoftLineBreak(SoftLineBreak softLineBreak)
|
||||
{
|
||||
writer.WriteElementString("softbreak", string.Empty);
|
||||
}
|
||||
|
||||
public override void VisitThematicBreak(ThematicBreak thematicBreak)
|
||||
{
|
||||
writer.WriteElementString("thematic_break", string.Empty);
|
||||
}
|
||||
|
||||
public override void VisitIndentedCodeBlock(IndentedCodeBlock codeBlock)
|
||||
{
|
||||
writer.WriteElementString("code_block", codeBlock.Value);
|
||||
}
|
||||
|
||||
public override void VisitFencedCodeBlock(FencedCodeBlock fencedCodeBlock)
|
||||
{
|
||||
writer.WriteStartElement("code_block");
|
||||
if (!string.IsNullOrEmpty(fencedCodeBlock.Info))
|
||||
{
|
||||
writer.WriteAttributeString("info", fencedCodeBlock.Info);
|
||||
}
|
||||
writer.WriteString(fencedCodeBlock.Value);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitHtmlBlock(HtmlBlock htmlBlock)
|
||||
{
|
||||
writer.WriteElementString("html_block", htmlBlock.Value);
|
||||
}
|
||||
|
||||
public override void VisitTable(Table table)
|
||||
{
|
||||
writer.WriteStartElement("table");
|
||||
base.VisitTable(table);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitTableHeaderRow(TableHeaderRow header)
|
||||
{
|
||||
writer.WriteStartElement("header");
|
||||
base.VisitTableHeaderRow(header);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitTableRow(TableRow row)
|
||||
{
|
||||
writer.WriteStartElement("row");
|
||||
base.VisitTableRow(row);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
|
||||
public override void VisitTableCell(TableCell cell)
|
||||
{
|
||||
writer.WriteStartElement("cell");
|
||||
if (cell.Alignment != TableCellAlignment.None)
|
||||
{
|
||||
writer.WriteAttributeString("align", cell.Alignment.ToString().ToLowerInvariant());
|
||||
}
|
||||
base.VisitTableCell(cell);
|
||||
writer.WriteEndElement();
|
||||
}
|
||||
}
|
||||
236
Radzen.Blazor.Tests/MaskTests.cs
Normal file
236
Radzen.Blazor.Tests/MaskTests.cs
Normal file
@@ -0,0 +1,236 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class MaskTests
|
||||
{
|
||||
[Fact]
|
||||
public void Mask_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
Assert.Contains(@$"rz-textbox", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"value=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_NameParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Name, value));
|
||||
|
||||
Assert.Contains(@$"name=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_TabIndexParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = 1;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.TabIndex, value));
|
||||
|
||||
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_PlaceholderParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Placeholder, value));
|
||||
|
||||
Assert.Contains(@$"placeholder=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"disabled", component.Markup);
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_ReadOnlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, value));
|
||||
|
||||
Assert.Contains(@$"readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_AutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.AdditionalName));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.AdditionalName.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Email));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.Email.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_MaxLengthParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var value = 10;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<long?>(p => p.MaxLength, value));
|
||||
|
||||
Assert.Contains(@$"maxlength=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Raises_ChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var raised = false;
|
||||
var value = "Test";
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("input").Change(value);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, newValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Mask_Raises_ValueChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMask>();
|
||||
|
||||
var raised = false;
|
||||
var value = "Test";
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("input").Change(value);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, newValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
65
Radzen.Blazor.Tests/MediaQueryTests.cs
Normal file
65
Radzen.Blazor.Tests/MediaQueryTests.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class MediaQueryTests
|
||||
{
|
||||
[Fact]
|
||||
public void MediaQuery_Renders()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMediaQuery>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Query, "(max-width: 768px)");
|
||||
});
|
||||
|
||||
Assert.NotNull(component.Instance);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MediaQuery_HasQueryParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var query = "(max-width: 1024px)";
|
||||
var component = ctx.RenderComponent<RadzenMediaQuery>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Query, query);
|
||||
});
|
||||
|
||||
Assert.Equal(query, component.Instance.Query);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void MediaQuery_InvokesChangeCallback()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
bool changeInvoked = false;
|
||||
bool matchResult = false;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenMediaQuery>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Query, "(max-width: 768px)");
|
||||
parameters.Add(p => p.Change, EventCallback.Factory.Create<bool>(this, (matches) =>
|
||||
{
|
||||
changeInvoked = true;
|
||||
matchResult = matches;
|
||||
}));
|
||||
});
|
||||
|
||||
// Invoke the JSInvokable method directly
|
||||
component.Instance.OnChange(true);
|
||||
|
||||
Assert.True(changeInvoked);
|
||||
Assert.True(matchResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
58
Radzen.Blazor.Tests/MenuTests.cs
Normal file
58
Radzen.Blazor.Tests/MenuTests.cs
Normal file
@@ -0,0 +1,58 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class MenuTests
|
||||
{
|
||||
[Fact]
|
||||
public void Menu_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenMenu>();
|
||||
|
||||
Assert.Contains(@"rz-menu", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Menu_Renders_Responsive_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Responsive, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-menu-closed", component.Markup);
|
||||
Assert.Contains("rz-menu-toggle", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Menu_Renders_Responsive_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Responsive, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-menu-toggle", component.Markup);
|
||||
Assert.DoesNotContain("rz-menu-closed", component.Markup);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Menu_Renders_CustomToggleAriaLabel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Responsive, true);
|
||||
parameters.Add(p => p.ToggleAriaLabel, "Open navigation");
|
||||
});
|
||||
|
||||
Assert.Contains("Open navigation", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
214
Radzen.Blazor.Tests/NotificationServiceTests.cs
Normal file
214
Radzen.Blazor.Tests/NotificationServiceTests.cs
Normal file
@@ -0,0 +1,214 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class NotificationServiceTests
|
||||
{
|
||||
[Fact]
|
||||
public void NotificationService_IsMessageIsNull_ExceptionExpected()
|
||||
{
|
||||
NotificationService notificationService = new NotificationService();
|
||||
NotificationMessage notificationMessage = null;
|
||||
|
||||
var exception = Record.Exception(() => notificationService.Notify(notificationMessage));
|
||||
|
||||
Assert.IsType<ArgumentNullException>(exception);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_Equals()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
Assert.True(messageOne.Equals(messageTwo));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_NotEquals()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary Two",
|
||||
Detail = "Info Detail Two",
|
||||
Duration = 6000
|
||||
};
|
||||
|
||||
Assert.False(messageOne.Equals(messageTwo));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_EqualsByReference()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = messageOne;
|
||||
|
||||
Assert.True(messageOne.Equals(messageTwo));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_EqualsByOperator()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
Assert.True(messageOne == messageTwo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_NotEqualsByOperator()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary Two",
|
||||
Detail = "Info Detail Two",
|
||||
Duration = 6000
|
||||
};
|
||||
|
||||
Assert.True(messageOne != messageTwo);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_EqualsByHashCode()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageOneHashCode = messageOne.GetHashCode();
|
||||
var messageTwoHashCode = messageTwo.GetHashCode();
|
||||
|
||||
Assert.Equal(messageOneHashCode, messageTwoHashCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_CheckAreTwoMessages_NotEqualsByHashCode()
|
||||
{
|
||||
var messageOne = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
};
|
||||
|
||||
var messageTwo = new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary Two",
|
||||
Detail = "Info Detail Tow",
|
||||
Duration = 5000
|
||||
};
|
||||
|
||||
var messageOneHashCode = messageOne.GetHashCode();
|
||||
var messageTwoHashCode = messageTwo.GetHashCode();
|
||||
|
||||
Assert.NotEqual(messageOneHashCode, messageTwoHashCode);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_MessagesCount_AfterAddingMessages()
|
||||
{
|
||||
NotificationService notificationService = new NotificationService();
|
||||
|
||||
//Messages are the same so only one should be added
|
||||
notificationService.Notify(NotificationSeverity.Info, "Info Summary", "Info Detail", 4000);
|
||||
notificationService.Notify(new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
});
|
||||
|
||||
int expectedMessagesNumber = 1;
|
||||
|
||||
Assert.Equal(expectedMessagesNumber, notificationService.Messages.Count);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void NotificationService_MessagesCount_AfterAddingTwoDifferentMessages()
|
||||
{
|
||||
NotificationService notificationService = new NotificationService();
|
||||
|
||||
//Messages are the same so only one should be added
|
||||
notificationService.Notify(NotificationSeverity.Info, "Info Summary 2", "Info Detail 2", 6000);
|
||||
notificationService.Notify(new NotificationMessage()
|
||||
{
|
||||
Severity = NotificationSeverity.Info,
|
||||
Summary = "Info Summary",
|
||||
Detail = "Info Detail",
|
||||
Duration = 4000
|
||||
});
|
||||
|
||||
int expectedMessagesNumber = 2;
|
||||
|
||||
Assert.Equal(expectedMessagesNumber, notificationService.Messages.Count);
|
||||
}
|
||||
}
|
||||
}
|
||||
176
Radzen.Blazor.Tests/NumericRangeValidatorTests.cs
Normal file
176
Radzen.Blazor.Tests/NumericRangeValidatorTests.cs
Normal file
@@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class NumericRangeValidatorTests
|
||||
{
|
||||
class FormComponentTestDouble : IRadzenFormComponent
|
||||
{
|
||||
public bool IsBound => false;
|
||||
|
||||
public bool HasValue => true;
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
public FieldIdentifier FieldIdentifier { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
|
||||
|
||||
public object GetValue()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
public ValueTask FocusAsync()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Disabled { get; set; }
|
||||
public bool Visible { get; set; }
|
||||
public IFormFieldContext FormFieldContext => null;
|
||||
|
||||
public object Value { get; set; }
|
||||
}
|
||||
|
||||
class RadzenNumericRangeValidatorTestDouble : RadzenNumericRangeValidator
|
||||
{
|
||||
public bool Validate(object value)
|
||||
{
|
||||
return base.Validate(new FormComponentTestDouble { Value = value });
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Throws_Exception_If_Min_And_Max_Are_Null()
|
||||
{
|
||||
var validator = new RadzenNumericRangeValidatorTestDouble();
|
||||
|
||||
Assert.Throws<System.ArgumentException>(() => validator.Validate(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_False_If_Value_Is_Null()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0).Add(p => p.Max, 10));
|
||||
});
|
||||
|
||||
Assert.False(component.Instance.Validate(null));
|
||||
}
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Null_And_AllowNull_Is_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0).Add(p => p.Max, 10).Add(p => p.AllowNull, true));
|
||||
});
|
||||
|
||||
Assert.True(component.Instance.Validate(null));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_False_If_Value_Overflows()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0).Add(p => p.Max, 10));
|
||||
});
|
||||
|
||||
Assert.False(component.Instance.Validate(long.MaxValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Greater_Than_Min()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0));
|
||||
|
||||
Assert.True(component.Instance.Validate(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Equal_To_Min()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0));
|
||||
|
||||
Assert.True(component.Instance.Validate(0));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Less_Than_Max()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Max, 10));
|
||||
|
||||
Assert.True(component.Instance.Validate(9));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Equal_To_Max()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Max, 10));
|
||||
|
||||
Assert.True(component.Instance.Validate(10));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Between_Min_And_Max()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0).Add(p => p.Max, 10));
|
||||
|
||||
Assert.True(component.Instance.Validate(5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_If_Value_Is_Between_Min_And_Max_And_They_Are_Nullable()
|
||||
{
|
||||
int? min = 0;
|
||||
int? max = 10;
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, min).Add(p => p.Max, max));
|
||||
Assert.True(component.Instance.Validate(5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_True_When_Value_Is_Of_DifferentType()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0m).Add(p => p.Max, 10m));
|
||||
|
||||
Assert.True(component.Instance.Validate(5));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Returns_False_If_Cannot_Conert_Value()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenNumericRangeValidatorTestDouble>();
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Min, 0m).Add(p => p.Max, 10m));
|
||||
|
||||
Assert.False(component.Instance.Validate(DateTime.Now));
|
||||
}
|
||||
}
|
||||
}
|
||||
641
Radzen.Blazor.Tests/NumericTests.cs
Normal file
641
Radzen.Blazor.Tests/NumericTests.cs
Normal file
@@ -0,0 +1,641 @@
|
||||
using System;
|
||||
using Bunit;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class NumericTests
|
||||
{
|
||||
[Fact]
|
||||
public void Numeric_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-numeric", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-up", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var value = 3.5;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<double>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"value=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Respect_MinParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var minValue = 2;
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
|
||||
parameters.Add<double>(p => p.Value, minValue);
|
||||
parameters.Add<decimal?>(p => p.Min, minValue);
|
||||
});
|
||||
|
||||
component.Find(".rz-numeric-down").Click();
|
||||
|
||||
Assert.False(raised, $"Numeric value should Change event if value is less than min value.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Respect_Nullable_With_MinParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double?>>();
|
||||
|
||||
var raised = false;
|
||||
var value = 3.5;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
parameters.Add<decimal?>(p => p.Min, 1);
|
||||
});
|
||||
|
||||
component.Find("input").Change(value);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, newValue));
|
||||
|
||||
component.Find("input").Change("");
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(null, newValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Respect_MaxParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var maxValue = 10;
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; }));
|
||||
parameters.Add<double>(p => p.Value, maxValue);
|
||||
parameters.Add<decimal?>(p => p.Max, maxValue);
|
||||
});
|
||||
|
||||
component.Find(".rz-numeric-up").Click();
|
||||
|
||||
Assert.False(raised, $"Numeric value should Change event if value is less than min value.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_NameParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Name, value));
|
||||
|
||||
Assert.Contains(@$"name=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_TabIndexParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var value = 1;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.TabIndex, value));
|
||||
|
||||
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_PlaceholderParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Placeholder, value));
|
||||
|
||||
Assert.Contains(@$"placeholder=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"disabled", component.Markup);
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_ReadOnlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, value));
|
||||
|
||||
Assert.Contains(@$"readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_AutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
|
||||
Assert.DoesNotContain(@$"aria-autocomplete", component.Markup);
|
||||
|
||||
component.Instance.DefaultAutoCompleteAttribute = "autocomplete-custom";
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""autocomplete-custom""", component.Markup);
|
||||
Assert.Contains(@$"aria-autocomplete=""none""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayMonth));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayMonth.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.BdayYear));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.BdayYear.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Raises_ChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var raised = false;
|
||||
var value = 3.5;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("input").Change(value);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, newValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Raises_ValueChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var raised = false;
|
||||
var value = 3.5;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("input").Change(value);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, newValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Raises_ChangedAndValueChangedEventOnStepUp()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var raised = false;
|
||||
var value = 3.5;
|
||||
var expectedValue = 5.5;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<double>(p => p.Value, value);
|
||||
parameters.Add(p => p.Step, "2");
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-numeric-up").Click();
|
||||
|
||||
Assert.True(raised, "Numeric Change should be raised on step up");
|
||||
Assert.True(object.Equals(expectedValue, newValue), $"Numeric value should be incremented on step up. Expected value: {expectedValue}, value: {newValue}");
|
||||
|
||||
raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
|
||||
|
||||
component.Find(".rz-numeric-up").Click();
|
||||
|
||||
Assert.True(raised, "Numeric ValueChanged should be raised on step up");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Raises_ChangedAndValueChangedEventOnStepDown()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
var raised = false;
|
||||
var value = 3.5;
|
||||
var expectedValue = 1.5;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<double>(p => p.Value, value);
|
||||
parameters.Add(p => p.Step, "2");
|
||||
parameters.Add(p => p.Change, args => { raised = true; newValue = args; });
|
||||
});
|
||||
|
||||
component.Find(".rz-numeric-down").Click();
|
||||
|
||||
Assert.True(raised, "Numeric Change should be raised on step up");
|
||||
Assert.True(object.Equals(expectedValue, newValue), $"Numeric value should be incremented on step up. Expected value: {expectedValue}, value: {newValue}");
|
||||
|
||||
raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; }));
|
||||
|
||||
component.Find(".rz-numeric-down").Click();
|
||||
|
||||
Assert.True(raised, "Numeric ValueChanged should be raised on step up");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_UpDown_Rendered()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-numeric-button-icon", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-up", component.Markup);
|
||||
Assert.Contains(@$"rz-numeric-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_UpDown_NotRenderedIfHidden()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>(ComponentParameter.CreateParameter(nameof(RadzenNumeric<double>.ShowUpDown), false));
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.DoesNotContain(@$"rz-numeric-button-icon", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-numeric-up", component.Markup);
|
||||
Assert.DoesNotContain(@$"rz-numeric-down", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Formatted()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
double valueToTest = 100.234;
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<double>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<double>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<double>.Value), valueToTest)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest.ToString(format)}\"", component.Markup);
|
||||
}
|
||||
|
||||
public static TheoryData<decimal, decimal> NumericFormatterPreservesLeadingZerosData =>
|
||||
new()
|
||||
{
|
||||
{ 10.000m, 100.000m },
|
||||
{ 100.000m, 10.000m }
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(NumericFormatterPreservesLeadingZerosData))]
|
||||
public void Numeric_Formatter_PreservesLeadingZeros(decimal oldValue, decimal newValue)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
string format = "0.000";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<decimal>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<decimal>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<decimal>.Value), oldValue)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{oldValue.ToString(format)}\"", component.Markup);
|
||||
|
||||
component.Find("input").Change(newValue);
|
||||
|
||||
Assert.Contains($" value=\"{newValue.ToString(format)}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Uses_ConvertValue()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var value = new Dollars(11m);
|
||||
Dollars? ConvertFunc(string s) => decimal.TryParse(s, System.Globalization.CultureInfo.InvariantCulture, out var val) ? new Dollars(val) : null;
|
||||
var component = ctx.RenderComponent<RadzenNumeric<Dollars?>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars?>.ConvertValue), (Func<string, Dollars?>)ConvertFunc),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars?>.Value), value),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{value.ToString()}\"", component.Markup);
|
||||
|
||||
var newValue = new Dollars(13.53m);
|
||||
component.Find("input").Change("13.53");
|
||||
|
||||
Assert.Contains($" value=\"{newValue.ToString()}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_TypeConverter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = new Dollars(100.234m);
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<Dollars>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Value), valueToTest)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest.ToString(format, System.Globalization.CultureInfo.CurrentCulture)}\"", component.Markup);
|
||||
}
|
||||
[Fact]
|
||||
public void Numeric_Supports_TypeConverterWithCulture()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = new Dollars(100.234m);
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<Dollars>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Value), valueToTest),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest.ToString(format, System.Globalization.CultureInfo.InvariantCulture)}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_EmptyString()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = "";
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<string>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"0.00\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_ValueString()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = "12.50";
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<string>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.InvariantCulture)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_ValueStringEsCLCulture()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = "12,50";
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<string>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.GetCultureInfo("es-CL"))
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_ValueStringEnUSCulture()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = "12.50";
|
||||
string format = "0.00";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<string>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<string>.Value), valueToTest),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Dollars>.Culture), System.Globalization.CultureInfo.GetCultureInfo("en-US"))
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains($" value=\"{valueToTest}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_IComparable()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<Dollars>>();
|
||||
|
||||
var maxValue = 2;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, new Dollars(1m));
|
||||
parameters.Add(p => p.Max, maxValue);
|
||||
});
|
||||
});
|
||||
|
||||
component.Find("input").Change(13.53);
|
||||
|
||||
var maxDollars = new Dollars(maxValue);
|
||||
Assert.Contains($" value=\"{maxDollars}\"", component.Markup);
|
||||
Assert.Equal(component.Instance.Value, maxDollars);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Numeric_Supports_IFormattable()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var valueToTest = new Temperature(60.23m);
|
||||
const string format = "F";
|
||||
|
||||
var component = ctx.RenderComponent<RadzenNumeric<Temperature>>(
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Temperature>.Format), format),
|
||||
ComponentParameter.CreateParameter(nameof(RadzenNumeric<Temperature>.Value), valueToTest)
|
||||
);
|
||||
|
||||
component.Render();
|
||||
|
||||
var input = component.Find("input").GetAttribute("value");
|
||||
input.MarkupMatches(valueToTest.ToString(format));
|
||||
}
|
||||
}
|
||||
}
|
||||
159
Radzen.Blazor.Tests/PagerTests.cs
Normal file
159
Radzen.Blazor.Tests/PagerTests.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using Bunit;
|
||||
using Bunit.JSInterop;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PagerTests
|
||||
{
|
||||
[Fact]
|
||||
public void RadzenPager_AutoHide_If_Count_Is_Less_Than_PageSize()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
});
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 101);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
});
|
||||
Assert.DoesNotContain(@$"rz-pager", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPager_Dont_AutoHide_If_PageSizeOptions_Specified()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 101);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<IEnumerable<int>>(p => p.PageSizeOptions, new int[] { 3, 7, 15 });
|
||||
});
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-pager", component.Markup);
|
||||
Assert.Contains(@$"rz-dropdown-trigger", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void RadzenPager_Renders_Summary() {
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters => {
|
||||
parameters.Add<int>(p => p.PageSize, 10);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, true);
|
||||
});
|
||||
await component.Instance.GoToPage(2);
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-pager-summary", component.Markup);
|
||||
Assert.Contains(@$"Page 3 of 10 (100 items)", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, false);
|
||||
});
|
||||
Assert.DoesNotContain(@$"rz-pager-summary", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPager_Renders_PagerDensityDefault()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<Density>(p => p.Density, Density.Default);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain(@$"rz-density-compact", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPager_Renders_PagerDensityCompact()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters =>
|
||||
{
|
||||
parameters.Add<int>(p => p.PageSize, 20);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<Density>(p => p.Density, Density.Compact);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"rz-density-compact", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void RadzenPager_First_And_Prev_Buttons_Are_Disabled_When_On_The_First_Page()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters => {
|
||||
parameters.Add<int>(p => p.PageSize, 10);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, true);
|
||||
});
|
||||
|
||||
await component.Instance.GoToPage(0);
|
||||
component.Render();
|
||||
|
||||
var firstPageButton = component.Find("a.rz-pager-first");
|
||||
Assert.True(firstPageButton.HasAttribute("disabled"));
|
||||
|
||||
var prevPageButton = component.Find("a.rz-pager-prev");
|
||||
Assert.True(prevPageButton.HasAttribute("disabled"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void RadzenPager_Last_And_Next_Buttons_Are_Disabled_When_On_The_Last_Page()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPager>(parameters => {
|
||||
parameters.Add<int>(p => p.PageSize, 10);
|
||||
parameters.Add<int>(p => p.Count, 100);
|
||||
parameters.Add<bool>(p => p.ShowPagingSummary, true);
|
||||
});
|
||||
|
||||
await component.Instance.GoToPage(9);
|
||||
component.Render();
|
||||
|
||||
var lastPageButton = component.Find("a.rz-pager-last");
|
||||
Assert.True(lastPageButton.HasAttribute("disabled"));
|
||||
|
||||
var nextPageButton = component.Find("a.rz-pager-next");
|
||||
Assert.True(nextPageButton.HasAttribute("disabled"));
|
||||
}
|
||||
}
|
||||
}
|
||||
116
Radzen.Blazor.Tests/PanelMenuTests.cs
Normal file
116
Radzen.Blazor.Tests/PanelMenuTests.cs
Normal file
@@ -0,0 +1,116 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Routing;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PanelMenuTests
|
||||
{
|
||||
class TestNavigationManager : NavigationManager
|
||||
{
|
||||
public TestNavigationManager(string uri)
|
||||
{
|
||||
Initialize("http://www.example.com/", uri);
|
||||
}
|
||||
|
||||
protected override void NavigateToCore(string uri, bool forceLoad)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, params string[] urls)
|
||||
=> CreatePanelMenu(currentAbsoluteUrl, match, new Dictionary<string, bool>(urls.Select(url => new KeyValuePair<string, bool>(url, false))));
|
||||
|
||||
private static string CreatePanelMenu(string currentAbsoluteUrl, NavLinkMatch match, Dictionary<string, bool> urls)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.Services.RemoveAll<NavigationManager>();
|
||||
ctx.Services.TryAddSingleton<NavigationManager>(new TestNavigationManager(currentAbsoluteUrl));
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanelMenu>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Match, match).AddChildContent(builder =>
|
||||
{
|
||||
foreach (var url in urls)
|
||||
{
|
||||
builder.OpenComponent<RadzenPanelMenuItem>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPanelMenuItem.Path), url.Key);
|
||||
builder.AddAttribute(2, nameof(RadzenPanelMenuItem.Disabled), url.Value);
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}));
|
||||
|
||||
return component.Markup;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_SetsOneActiveMenuItem()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/datagrid-dynamic", NavLinkMatch.All, "/datagrid", "/datagrid-dynamic");
|
||||
|
||||
var firstIndex = component.IndexOf("rz-navigation-item-wrapper-active");
|
||||
var lastIndex = component.LastIndexOf("rz-navigation-item-wrapper-active");
|
||||
|
||||
Assert.NotEqual(-1, firstIndex);
|
||||
Assert.Equal(firstIndex, lastIndex);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_CanDisableMenuItem()
|
||||
{
|
||||
var urls = new Dictionary<string, bool>
|
||||
{
|
||||
{"/datagrid", false},
|
||||
{"/disabled-url", true}
|
||||
};
|
||||
var component = CreatePanelMenu("http://www.example.com/", NavLinkMatch.All, urls);
|
||||
|
||||
Assert.Contains("rz-state-disabled", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_MatchesQueryStringParameters()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.Prefix, "/foo");
|
||||
|
||||
Assert.Contains("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_DoesNotMatchQueryStringParametersWhenExactMatchIsSpecified()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/foo?bar", NavLinkMatch.All, "/foo");
|
||||
|
||||
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_DoesNotMatchRootWithEverything()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/foo", NavLinkMatch.Prefix, "/");
|
||||
|
||||
Assert.DoesNotContain("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_MatchesRoot()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com/", NavLinkMatch.Prefix, "/");
|
||||
|
||||
Assert.Contains("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadzenPanelMenu_MatchesRootWithoutTrailingSlash()
|
||||
{
|
||||
var component = CreatePanelMenu("http://www.example.com", NavLinkMatch.Prefix, "/");
|
||||
|
||||
Assert.Contains("rz-navigation-item-wrapper-active", component);
|
||||
}
|
||||
}
|
||||
}
|
||||
229
Radzen.Blazor.Tests/PanelTests.cs
Normal file
229
Radzen.Blazor.Tests/PanelTests.cs
Normal file
@@ -0,0 +1,229 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PanelTests
|
||||
{
|
||||
[Fact]
|
||||
public void Panel_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-panel", component.Markup);
|
||||
Assert.Contains(@$"rz-panel-titlebar", component.Markup);
|
||||
Assert.Contains(@$"rz-panel-content-wrapper", component.Markup);
|
||||
Assert.Contains(@$"rz-panel-content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, value));
|
||||
|
||||
Assert.Contains(@$"<span>{value}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, value));
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rzi"">{value}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_ChildContentParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var value = "MyChildContent";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ChildContent, value));
|
||||
|
||||
Assert.Contains(@$"{value}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_HeaderTemplateParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var value = "MyHeaderTemplate";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.HeaderTemplate, value));
|
||||
|
||||
Assert.Contains(@$"{value}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_FooterTemplateParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var value = "MyFooterTemplate";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.FooterTemplate, value));
|
||||
|
||||
Assert.Contains(@$"{value}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_AllowCollapseParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var classes = @"class=""rz-panel-titlebar-icon rz-panel-titlebar-toggler""";
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.DoesNotContain(classes, component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
|
||||
|
||||
Assert.Contains(classes, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_CollapsedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.AllowCollapse, true));
|
||||
|
||||
Assert.Contains(@"<span class=""notranslate rzi rzi-minus""></span>", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Collapsed, true));
|
||||
|
||||
Assert.Contains(@"<span class=""notranslate rzi rzi-plus""></span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Raises_ExpandAndCollapseEvents()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
var raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add(p => p.Collapse, args => { raised = true; });
|
||||
});
|
||||
|
||||
component.Find("a").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
|
||||
raised = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Expand, args => { raised = true; }));
|
||||
|
||||
component.Find("a").Click();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_Renders_SummaryWhenCollapsed()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, true);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Panel_DoesNotRender_SummaryWhenOpen()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenPanel>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add<bool>(p => p.AllowCollapse, true);
|
||||
parameters.Add<bool>(p => p.Collapsed, false);
|
||||
parameters.Add<RenderFragment>(p => p.SummaryTemplate, builder =>
|
||||
{
|
||||
builder.OpenElement(0, "p");
|
||||
builder.AddContent(0, "SummaryContent");
|
||||
builder.CloseElement();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Assert.Contains("SummaryContent", component.Markup);
|
||||
Assert.Equal(
|
||||
"true",
|
||||
component.Find(".rz-panel-content-summary").ParentElement.ParentElement.Attributes.First(attr => attr.Name == "aria-hidden").Value
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
238
Radzen.Blazor.Tests/PasswordTests.cs
Normal file
238
Radzen.Blazor.Tests/PasswordTests.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PasswordTests
|
||||
{
|
||||
[Fact]
|
||||
public void Password_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
Assert.Contains(@$"rz-textbox", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"value=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_NameParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Name, value));
|
||||
|
||||
Assert.Contains(@$"name=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_TabIndexParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var value = 1;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.TabIndex, value));
|
||||
|
||||
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_PlaceholderParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Placeholder, value));
|
||||
|
||||
Assert.Contains(@$"placeholder=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"disabled", component.Markup);
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_ReadOnlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, value));
|
||||
|
||||
Assert.Contains(@$"readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_AutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""on""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autocomplete", "custom"));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""custom""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_TypedAutoCompleteParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", false));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.On));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""new-password""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.Off));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""off""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.CurrentPassword));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.CurrentPassword.GetAutoCompleteValue()}""", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("AutoComplete", true));
|
||||
component.SetParametersAndRender(parameters => parameters.Add<AutoCompleteType>(p => p.AutoCompleteType, AutoCompleteType.NewPassword));
|
||||
|
||||
Assert.Contains(@$"autocomplete=""{AutoCompleteType.NewPassword.GetAutoCompleteValue()}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Raises_ChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var hasRaised = false;
|
||||
var value = "Test";
|
||||
object newValue = null;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { hasRaised = true; newValue = args; });
|
||||
parameters.Add(p => p.Immediate, false);
|
||||
});
|
||||
|
||||
var inputElement = component.Find("input");
|
||||
inputElement.Change(value);
|
||||
|
||||
Assert.DoesNotContain("oninput", inputElement.ToMarkup());
|
||||
Assert.True(hasRaised);
|
||||
Assert.Equal(value, newValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Raises_InputEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var hasRaised = false;
|
||||
var value = "Test";
|
||||
object newValue = null;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Change, args => { hasRaised = true; newValue = args; });
|
||||
parameters.Add(p => p.Immediate, true);
|
||||
});
|
||||
|
||||
var inputElement = component.Find("input");
|
||||
inputElement.Input(value);
|
||||
|
||||
Assert.DoesNotContain("onchange", inputElement.ToMarkup());
|
||||
Assert.True(hasRaised);
|
||||
Assert.Equal(value, newValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Password_Raises_ValueChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPassword>();
|
||||
|
||||
var raised = false;
|
||||
var value = "Test";
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("input").Change(value);
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, newValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
161
Radzen.Blazor.Tests/PickListTests.cs
Normal file
161
Radzen.Blazor.Tests/PickListTests.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PickListTests
|
||||
{
|
||||
class Item
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>();
|
||||
|
||||
Assert.Contains(@"rz-picklist", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_SourceAndTargetLists()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>();
|
||||
|
||||
Assert.Contains("rz-picklist-source-wrapper", component.Markup);
|
||||
Assert.Contains("rz-picklist-target-wrapper", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_TransferButtons()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>();
|
||||
|
||||
Assert.Contains("rz-picklist-buttons", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_Orientation_Horizontal()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Horizontal);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-flex-row", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_Orientation_Vertical()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Vertical);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-flex-column", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_AllowFiltering()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<Item>
|
||||
{
|
||||
new Item { Id = 1, Name = "Item 1" }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
parameters.Add(p => p.Source, data);
|
||||
parameters.Add(p => p.TextProperty, "Name");
|
||||
});
|
||||
|
||||
Assert.Contains("rz-listbox-filter", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_SourceData()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<Item>
|
||||
{
|
||||
new Item { Id = 1, Name = "Source Item 1" },
|
||||
new Item { Id = 2, Name = "Source Item 2" }
|
||||
};
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Source, data);
|
||||
parameters.Add(p => p.TextProperty, "Name");
|
||||
});
|
||||
|
||||
Assert.Contains("Source Item 1", component.Markup);
|
||||
Assert.Contains("Source Item 2", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_ShowHeader()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowHeader, true);
|
||||
parameters.Add(p => p.SourceHeader, builder => builder.AddContent(0, "Available Items"));
|
||||
parameters.Add(p => p.TargetHeader, builder => builder.AddContent(0, "Selected Items"));
|
||||
});
|
||||
|
||||
Assert.Contains("Available Items", component.Markup);
|
||||
Assert.Contains("Selected Items", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_AllowMoveAll_Buttons()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var data = new List<Item> { new Item { Id = 1, Name = "Item" } };
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowMoveAll, true);
|
||||
parameters.Add(p => p.Source, data);
|
||||
});
|
||||
|
||||
// Should have 4 buttons when AllowMoveAll is true
|
||||
var buttonCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-button").Count;
|
||||
Assert.True(buttonCount >= 4);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PickList_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenPickList<Item>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
644
Radzen.Blazor.Tests/PivotDataGridTests.cs
Normal file
644
Radzen.Blazor.Tests/PivotDataGridTests.cs
Normal file
@@ -0,0 +1,644 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Radzen;
|
||||
using Radzen.Blazor;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PivotDataGridTests
|
||||
{
|
||||
private static readonly List<SalesData> SampleData = new()
|
||||
{
|
||||
new SalesData { Region = "North", Category = "Electronics", Product = "Laptop", Amount = 1000, Year = 2023 },
|
||||
new SalesData { Region = "North", Category = "Electronics", Product = "Laptop", Amount = 1500, Year = 2024 },
|
||||
new SalesData { Region = "South", Category = "Home", Product = "Vacuum", Amount = 500, Year = 2023 }
|
||||
};
|
||||
|
||||
public class SalesData
|
||||
{
|
||||
public string Region { get; set; }
|
||||
public string Category { get; set; }
|
||||
public string Product { get; set; }
|
||||
public double Amount { get; set; }
|
||||
public int Year { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_CssClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx);
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-pivot-data-grid", component.Markup);
|
||||
Assert.Contains("rz-pivot-table", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_RowAndColumnHeaders()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx);
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var table = component.Find(".rz-pivot-content .rz-pivot-table");
|
||||
var headers = table.GetElementsByClassName("rz-pivot-header-text").Select(h => h.TextContent.Trim()).ToList();
|
||||
var aggregateHeaders = table.GetElementsByClassName("rz-pivot-aggregate-header").Select(h => h.TextContent.Trim()).ToList();
|
||||
|
||||
Assert.Contains("Region", headers);
|
||||
Assert.Contains("2023", headers);
|
||||
Assert.Contains("Sales", aggregateHeaders);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowSorting_RendersSortableClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowSorting, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var sortableHeaders = component.FindAll(".rz-pivot-header-content.rz-sortable");
|
||||
Assert.NotEmpty(sortableHeaders);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowFiltering_RendersFilterIcon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var filterIcons = component.FindAll(".rz-grid-filter-icon");
|
||||
Assert.NotEmpty(filterIcons);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_AggregateValues()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx);
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("1000", component.Markup);
|
||||
Assert.Contains("1500", component.Markup);
|
||||
Assert.Contains("500", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_DisallowFiltering_HidesFilterIcon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFiltering, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var filterIcons = component.FindAll(".rz-grid-filter-icon");
|
||||
Assert.Empty(filterIcons);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_DisallowSorting_HidesSortableClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowSorting, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var sortableHeaders = component.FindAll(".rz-pivot-header-content.rz-sortable");
|
||||
Assert.Empty(sortableHeaders);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_ShowColumnsTotals_RendersFooter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowColumnsTotals, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var footer = component.FindAll(".rz-pivot-footer");
|
||||
Assert.NotEmpty(footer);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_HideColumnsTotals_NoFooter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowColumnsTotals, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var footer = component.FindAll(".rz-pivot-footer");
|
||||
Assert.Empty(footer);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_DefaultEmptyText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, new List<SalesData>());
|
||||
parameters.Add(p => p.AllowFieldsPicking, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("No records to display.", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_CustomEmptyText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, new List<SalesData>());
|
||||
parameters.Add(p => p.EmptyText, "No data available");
|
||||
parameters.Add(p => p.AllowFieldsPicking, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("No data available", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowPaging_RendersPager()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.PageSize, 2);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-pager", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_DisallowPaging_HidesPager()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.DoesNotContain("rz-pager", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_PagerPosition_Top()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.PagerPosition, PagerPosition.Top);
|
||||
parameters.Add(p => p.PageSize, 2);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-pager", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_PagerPosition_TopAndBottom()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.PagerPosition, PagerPosition.TopAndBottom);
|
||||
parameters.Add(p => p.PageSize, 2);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var pagers = component.FindAll(".rz-pager");
|
||||
Assert.True(pagers.Count >= 1); // Should have at least one pager
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Density_Compact()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowPaging, true);
|
||||
parameters.Add(p => p.PageSize, 1); // Force pager to show with small page size
|
||||
parameters.Add(p => p.AllowFieldsPicking, false);
|
||||
parameters.Add(p => p.Density, Density.Compact);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-density-compact", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowAlternatingRows_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowAlternatingRows, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-grid-table-striped", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowAlternatingRows_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowAlternatingRows, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.DoesNotContain("rz-grid-table-striped", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowFieldsPicking_ShowsPanel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFieldsPicking, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-panel", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowFieldsPicking_False_HidesPanel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowFieldsPicking, false);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.DoesNotContain("rz-panel", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_AllowDrillDown()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowDrillDown, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
// Should render pivot content
|
||||
Assert.Contains("rz-pivot-content", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_RowValues()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx);
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var cells = component.FindAll(".rz-pivot-row-header");
|
||||
var cellTexts = cells.Select(c => c.TextContent.Trim()).ToList();
|
||||
|
||||
Assert.Contains("North", cellTexts);
|
||||
Assert.Contains("South", cellTexts);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_MultipleRows()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, SampleData);
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Rows, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotRow<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Region));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotRow<SalesData>.Title), "Region");
|
||||
builder.CloseComponent();
|
||||
|
||||
builder.OpenComponent<RadzenPivotRow<SalesData>>(2);
|
||||
builder.AddAttribute(3, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Category));
|
||||
builder.AddAttribute(4, nameof(RadzenPivotRow<SalesData>.Title), "Category");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotColumn<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotColumn<SalesData>.Property), nameof(SalesData.Year));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotColumn<SalesData>.Title), "Year");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Aggregates, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotAggregate<SalesData>.Title), "Sales");
|
||||
builder.AddAttribute(3, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Sum);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var headers = component.FindAll(".rz-pivot-header-text").Select(h => h.TextContent.Trim()).ToList();
|
||||
Assert.Contains("Region", headers);
|
||||
Assert.Contains("Category", headers);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_MultipleAggregates()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, SampleData);
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Rows, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotRow<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Region));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotRow<SalesData>.Title), "Region");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotColumn<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotColumn<SalesData>.Property), nameof(SalesData.Year));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotColumn<SalesData>.Title), "Year");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Aggregates, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotAggregate<SalesData>.Title), "Total Sales");
|
||||
builder.AddAttribute(3, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Sum);
|
||||
builder.CloseComponent();
|
||||
|
||||
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(4);
|
||||
builder.AddAttribute(5, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
|
||||
builder.AddAttribute(6, nameof(RadzenPivotAggregate<SalesData>.Title), "Count Sales");
|
||||
builder.AddAttribute(7, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Count);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
var aggregateHeaders = component.FindAll(".rz-pivot-aggregate-header").Select(h => h.TextContent.Trim()).ToList();
|
||||
Assert.Contains("Total Sales", aggregateHeaders);
|
||||
Assert.Contains("Count Sales", aggregateHeaders);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_Renders_AlternatingRowClasses()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = RenderPivotDataGrid(ctx, parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowAlternatingRows, true);
|
||||
});
|
||||
|
||||
component.WaitForAssertion(() =>
|
||||
{
|
||||
Assert.Contains("rz-pivot-row-even", component.Markup);
|
||||
Assert.Contains("rz-pivot-row-odd", component.Markup);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_PageSize_DefaultsTo10()
|
||||
{
|
||||
var grid = new RadzenPivotDataGrid<SalesData>();
|
||||
Assert.Equal(10, grid.PageSize);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowSorting_DefaultsToTrue()
|
||||
{
|
||||
var grid = new RadzenPivotDataGrid<SalesData>();
|
||||
Assert.True(grid.AllowSorting);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowFiltering_DefaultsToTrue()
|
||||
{
|
||||
var grid = new RadzenPivotDataGrid<SalesData>();
|
||||
Assert.True(grid.AllowFiltering);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowAlternatingRows_DefaultsToTrue()
|
||||
{
|
||||
var grid = new RadzenPivotDataGrid<SalesData>();
|
||||
Assert.True(grid.AllowAlternatingRows);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowDrillDown_DefaultsToTrue()
|
||||
{
|
||||
var grid = new RadzenPivotDataGrid<SalesData>();
|
||||
Assert.True(grid.AllowDrillDown);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PivotDataGrid_AllowFieldsPicking_DefaultsToTrue()
|
||||
{
|
||||
var grid = new RadzenPivotDataGrid<SalesData>();
|
||||
Assert.True(grid.AllowFieldsPicking);
|
||||
}
|
||||
|
||||
private static IRenderedComponent<RadzenPivotDataGrid<SalesData>> RenderPivotDataGrid(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenPivotDataGrid<SalesData>>>? configure = null)
|
||||
{
|
||||
return ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Data, SampleData);
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Rows, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotRow<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotRow<SalesData>.Property), nameof(SalesData.Region));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotRow<SalesData>.Title), "Region");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Columns, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotColumn<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotColumn<SalesData>.Property), nameof(SalesData.Year));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotColumn<SalesData>.Title), "Year");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
parameters.Add<RenderFragment>(p => p.Aggregates, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenPivotAggregate<SalesData>>(0);
|
||||
builder.AddAttribute(1, nameof(RadzenPivotAggregate<SalesData>.Property), nameof(SalesData.Amount));
|
||||
builder.AddAttribute(2, nameof(RadzenPivotAggregate<SalesData>.Title), "Sales");
|
||||
builder.AddAttribute(3, nameof(RadzenPivotAggregate<SalesData>.Aggregate), AggregateFunction.Sum);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
|
||||
configure?.Invoke(parameters);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
120
Radzen.Blazor.Tests/ProfileMenuItemTests.cs
Normal file
120
Radzen.Blazor.Tests/ProfileMenuItemTests.cs
Normal file
@@ -0,0 +1,120 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ProfileMenuItemTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProfileMenuItem_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenProfileMenuItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Profile");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("Profile", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProfileMenuItem_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenProfileMenuItem>(0);
|
||||
builder.AddAttribute(1, "Icon", "account_circle");
|
||||
builder.AddAttribute(2, "Text", "Profile");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("account_circle", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProfileMenuItem_Template_OverridesText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenProfileMenuItem>(0);
|
||||
builder.AddAttribute(1, "Text", "This should not appear");
|
||||
builder.AddAttribute(2, "Template", (RenderFragment)((templateBuilder) =>
|
||||
{
|
||||
templateBuilder.OpenElement(0, "span");
|
||||
templateBuilder.AddAttribute(1, "class", "template-content");
|
||||
templateBuilder.AddContent(2, "Template Content");
|
||||
templateBuilder.CloseElement();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Template should be rendered
|
||||
Assert.Contains("template-content", component.Markup);
|
||||
// Text should not be rendered in navigation-item-text span when Template is present
|
||||
Assert.DoesNotContain("<span class=\"rz-navigation-item-text\">This should not appear</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProfileMenuItem_Renders_TemplateWithSwitch()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenProfileMenuItem>(0);
|
||||
builder.AddAttribute(1, "Icon", "settings");
|
||||
builder.AddAttribute(2, "Template", (RenderFragment)((templateBuilder) =>
|
||||
{
|
||||
templateBuilder.OpenComponent<RadzenSwitch>(0);
|
||||
templateBuilder.CloseComponent();
|
||||
}));
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Icon should still be rendered
|
||||
Assert.Contains("settings", component.Markup);
|
||||
// Switch should be rendered from template
|
||||
Assert.Contains("rz-switch", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProfileMenuItem_Renders_PathParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProfileMenu>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ChildContent, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenProfileMenuItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Settings");
|
||||
builder.AddAttribute(2, "Path", "/settings");
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.Contains("href=\"/settings\"", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
186
Radzen.Blazor.Tests/ProgressBarTests.cs
Normal file
186
Radzen.Blazor.Tests/ProgressBarTests.cs
Normal file
@@ -0,0 +1,186 @@
|
||||
using Bunit;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class ProgressBarTests
|
||||
{
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
var value = 4.5;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<double>(p => p.Value, value));
|
||||
|
||||
|
||||
Assert.Contains(@$"<div class=""rz-progressbar-label"">", component.Markup);
|
||||
Assert.Contains(@$"{value}%", component.Markup);
|
||||
Assert.Contains(@$"aria-valuenow=""{value}""", component.Markup);
|
||||
Assert.Contains(@$"aria-valuemin=""0""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_MaxParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"aria-valuemax=""{100}""", component.Markup);
|
||||
|
||||
var value = 500;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<double>(p => p.Max, value));
|
||||
|
||||
Assert.Contains(@$"aria-valuemax=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_UnitParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"0%", component.Markup);
|
||||
|
||||
var unit = "mm";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Unit, unit));
|
||||
|
||||
Assert.Contains(@$"0{unit}", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""--rz-progressbar-value: 0%;{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_ModeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Contains(@$"rz-progressbar-determinate", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<ProgressBarMode>(p => p.Mode, ProgressBarMode.Indeterminate));
|
||||
|
||||
Assert.Contains(@$"rz-progressbar-indeterminate", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_WidthFromValueAndMaxParameters()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
var value = 4.5;
|
||||
var max = 500;
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<double>(p => p.Value, value);
|
||||
parameters.Add<double>(p => p.Max, max);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"style=""--rz-progressbar-value: {Math.Min(value / max * 100, 100).ToInvariantString()}%;""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_ProgressBarStyle()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>();
|
||||
|
||||
component.SetParametersAndRender(parameters=>parameters.Add(p=>p.ProgressBarStyle, ProgressBarStyle.Success));
|
||||
Assert.Contains(@$"rz-progressbar-success", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
|
||||
Assert.Contains(@$"rz-progressbar-info", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Success));
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
|
||||
Assert.Contains(@$"rz-progressbar-success", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ProgressBarStyle, ProgressBarStyle.Info));
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Mode, ProgressBarMode.Indeterminate));
|
||||
Assert.Contains(@$"rz-progressbar-info", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_ShowValue_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowValue, true);
|
||||
parameters.Add(p => p.Value, 50);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-progressbar-label", component.Markup);
|
||||
Assert.Contains("50%", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_ShowValue_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowValue, false);
|
||||
parameters.Add(p => p.Value, 50);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-progressbar-label", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProgressBar_Renders_Template()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenProgressBar>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, 75);
|
||||
parameters.Add(p => p.Template, builder => builder.AddContent(0, "Custom: 75%"));
|
||||
});
|
||||
|
||||
Assert.Contains("Custom: 75%", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
155
Radzen.Blazor.Tests/PropertyAccessTests.cs
Normal file
155
Radzen.Blazor.Tests/PropertyAccessTests.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class PropertyAccessTests
|
||||
{
|
||||
public partial class TestData
|
||||
{
|
||||
public string PROPERTY { get; set; }
|
||||
public string Property { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_With_DifferentTargetType()
|
||||
{
|
||||
var o = new TestData { Property = "test" };
|
||||
var getter = PropertyAccess.Getter<object, object>(nameof(TestData.Property), typeof(TestData));
|
||||
var value = getter(o);
|
||||
Assert.Equal(o.Property, value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_With_Members_That_Differ_Only_In_Casing()
|
||||
{
|
||||
var o = new TestData { PROPERTY = nameof(TestData.PROPERTY), Property = nameof(TestData.Property) };
|
||||
var getter = PropertyAccess.Getter<TestData, string>(nameof(TestData.PROPERTY));
|
||||
var value = getter(o);
|
||||
Assert.Equal(nameof(TestData.PROPERTY), value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_On_Simple_Object()
|
||||
{
|
||||
var o = new SimpleObject() { Prop1 = "TestString" };
|
||||
var getter = PropertyAccess.Getter<SimpleObject, string>("Prop1");
|
||||
var value = getter(o);
|
||||
Assert.Equal("TestString", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_On_Simple_Object_QueryableType()
|
||||
{
|
||||
var _data = new List<SimpleObject>()
|
||||
{
|
||||
new SimpleObject() { Prop1 = "TestString" },
|
||||
};
|
||||
|
||||
Func<object, object> getter = PropertyAccess.Getter<object, object>("Prop1", typeof(SimpleObject));
|
||||
|
||||
var value = getter(_data[0]);
|
||||
Assert.Equal("TestString", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_On_Nested_Object()
|
||||
{
|
||||
var o = new NestedObject() { Obj = new SimpleObject { Prop1 = "TestString" } };
|
||||
var getter = PropertyAccess.Getter<NestedObject, string>("Obj.Prop1");
|
||||
var value = getter(o);
|
||||
Assert.Equal("TestString", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_From_Array()
|
||||
{
|
||||
var o = new ArrayObject() { Values = new string[] { "1", "2", "3" } };
|
||||
var getter = PropertyAccess.Getter<ArrayObject, string>("Values[1]");
|
||||
var value = getter(o);
|
||||
Assert.Equal("2", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_From_Nested_Array()
|
||||
{
|
||||
var o = new NestedArrayObject() { Obj = new ArrayObject() { Values = new string[] { "1", "2", "3" } } };
|
||||
var getter = PropertyAccess.Getter<NestedArrayObject, string>("Obj.Values[2]");
|
||||
var value = getter(o);
|
||||
Assert.Equal("3", value);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Getter_Resolves_Property_From_List()
|
||||
{
|
||||
var o = new ListObject() { Values = new List<string>() { "1", "2", "3" } };
|
||||
var getter = PropertyAccess.Getter<ListObject, string>("Values[1]");
|
||||
var value = getter(o);
|
||||
Assert.Equal("2", value);
|
||||
}
|
||||
|
||||
public class SimpleObject
|
||||
{
|
||||
public string Prop1 { get; set; }
|
||||
}
|
||||
|
||||
public class NestedObject
|
||||
{
|
||||
public SimpleObject Obj { get; set; }
|
||||
}
|
||||
|
||||
public class ArrayObject
|
||||
{
|
||||
public string[] Values { get; set; }
|
||||
}
|
||||
|
||||
public class NestedArrayObject
|
||||
{
|
||||
public ArrayObject Obj { get; set; }
|
||||
}
|
||||
|
||||
public class ListObject
|
||||
{
|
||||
public List<string> Values { get; set; }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProperty_Should_Resolve_DescriptionProperty()
|
||||
{
|
||||
var descriptionProperty = PropertyAccess.GetProperty(typeof(ISimpleInterface), nameof(ISimpleInterface.Description));
|
||||
|
||||
Assert.NotNull(descriptionProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProperty_Should_Resolve_NameProperty()
|
||||
{
|
||||
var nameProperty = PropertyAccess.GetProperty(typeof(ISimpleInterface), nameof(ISimpleInterface.Name));
|
||||
|
||||
Assert.NotNull(nameProperty);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProperty_Should_Resolve_IdProperty()
|
||||
{
|
||||
var idProperty = PropertyAccess.GetProperty(typeof(ISimpleInterface), nameof(ISimpleBaseInterface.Id));
|
||||
Assert.NotNull(idProperty);
|
||||
}
|
||||
|
||||
interface ISimpleInterface : ISimpleNestedInterface
|
||||
{
|
||||
string Description { get; set; }
|
||||
}
|
||||
|
||||
interface ISimpleNestedInterface : ISimpleBaseInterface
|
||||
{
|
||||
string Name { get; set; }
|
||||
}
|
||||
|
||||
interface ISimpleBaseInterface
|
||||
{
|
||||
int Id { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
2526
Radzen.Blazor.Tests/QueryableExtensionTests.cs
Normal file
2526
Radzen.Blazor.Tests/QueryableExtensionTests.cs
Normal file
File diff suppressed because it is too large
Load Diff
62
Radzen.Blazor.Tests/RadioButtonListTests.cs
Normal file
62
Radzen.Blazor.Tests/RadioButtonListTests.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Bunit;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class RadioButtonListTests
|
||||
{
|
||||
[Fact]
|
||||
public void RadioButtonList_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRadioButtonList<int>>();
|
||||
|
||||
Assert.Contains(@"rz-radio-button-list", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadioButtonList_Renders_Orientation()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRadioButtonList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenRadioButtonListItem<int>>(0);
|
||||
builder.AddAttribute(1, "Text", "Option 1");
|
||||
builder.AddAttribute(2, "Value", 1);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
|
||||
// Orientation is applied via RadzenStack which uses flex-direction
|
||||
Assert.Contains("rz-flex-row", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
|
||||
Assert.Contains("rz-flex-column", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RadioButtonList_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRadioButtonList<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenRadioButtonListItem<int>>(0);
|
||||
builder.AddAttribute(1, "Text", "Option 1");
|
||||
builder.AddAttribute(2, "Value", 1);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
// Disabled class is on the radio button items
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
Radzen.Blazor.Tests/Radzen.Blazor.Tests.csproj
Normal file
27
Radzen.Blazor.Tests/Radzen.Blazor.Tests.csproj
Normal file
@@ -0,0 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
|
||||
<PackageReference Include="bunit.web" Version="1.36.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Radzen.Blazor\Radzen.Blazor.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
82
Radzen.Blazor.Tests/RatingTests.cs
Normal file
82
Radzen.Blazor.Tests/RatingTests.cs
Normal file
@@ -0,0 +1,82 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class RatingTests
|
||||
{
|
||||
[Fact]
|
||||
public void Rating_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRating>();
|
||||
|
||||
Assert.Contains(@"rz-rating", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rating_Renders_Stars()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRating>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Stars, 5));
|
||||
|
||||
// Should render 5 star icons (rzi-star or rzi-star-o) + 1 clear button icon = 6 total
|
||||
var starCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-rating-icon").Count;
|
||||
Assert.Equal(6, starCount); // 5 stars + 1 clear button
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rating_Renders_CustomStarCount()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRating>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Stars, 10));
|
||||
|
||||
var starCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rz-rating-icon").Count;
|
||||
Assert.Equal(11, starCount); // 10 stars + 1 clear button
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rating_Renders_Value()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRating>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Value, 3);
|
||||
parameters.Add(p => p.Stars, 5);
|
||||
});
|
||||
|
||||
// Should have 3 filled stars (rzi-star) and 2 outline stars (rzi-star-o)
|
||||
var filledStars = System.Text.RegularExpressions.Regex.Matches(component.Markup, "rzi-star\"").Count;
|
||||
Assert.Equal(3, filledStars);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rating_Renders_ReadOnly()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRating>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ReadOnly, true));
|
||||
|
||||
Assert.Contains("rz-state-readonly", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Rating_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRating>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
Radzen.Blazor.Tests/Rendering/StepGeneratorTests.cs
Normal file
25
Radzen.Blazor.Tests/Rendering/StepGeneratorTests.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests.Rendering;
|
||||
|
||||
public class StepGeneratorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Renders_Path_Correctly()
|
||||
{
|
||||
var data = new List<Point>
|
||||
{
|
||||
new() { X = 10, Y = 10 },
|
||||
new() { X = 20, Y = 15 },
|
||||
new() { X = 30, Y = 20 },
|
||||
new() { X = 40, Y = 25 },
|
||||
new() { X = 50, Y = 50 }
|
||||
};
|
||||
|
||||
var path = new StepGenerator().Path(data);
|
||||
|
||||
Assert.Equal("10 10 H 20 V 15 H 30 V 20 H 40 V 25 H 50 V 50", path);
|
||||
}
|
||||
}
|
||||
63
Radzen.Blazor.Tests/RowTests.cs
Normal file
63
Radzen.Blazor.Tests/RowTests.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class RowTests
|
||||
{
|
||||
[Fact]
|
||||
public void Row_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRow>();
|
||||
|
||||
Assert.Contains(@"rz-row", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Row_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRow>(parameters =>
|
||||
{
|
||||
parameters.AddChildContent("<div>Row Content</div>");
|
||||
});
|
||||
|
||||
Assert.Contains("Row Content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Row_Renders_Gap()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRow>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Gap, "2rem"));
|
||||
|
||||
Assert.Contains("--rz-gap:2rem", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Row_Renders_RowGap()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRow>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.RowGap, "1.5rem"));
|
||||
|
||||
Assert.Contains("--rz-row-gap:1.5rem", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Row_Renders_ColumnGap()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenRow>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Gap, "1rem"));
|
||||
|
||||
Assert.Contains("--rz-gap:1rem", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
45
Radzen.Blazor.Tests/SecurityCodeTests.cs
Normal file
45
Radzen.Blazor.Tests/SecurityCodeTests.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SecurityCodeTests
|
||||
{
|
||||
[Fact]
|
||||
public void SecurityCode_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenSecurityCode>();
|
||||
|
||||
Assert.Contains(@"rz-security-code", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SecurityCode_Renders_Count()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenSecurityCode>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Count, 6));
|
||||
|
||||
// Should render 6 input boxes + 1 hidden input for form submission = 7 total
|
||||
var inputCount = System.Text.RegularExpressions.Regex.Matches(component.Markup, "<input").Count;
|
||||
Assert.Equal(7, inputCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SecurityCode_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
var component = ctx.RenderComponent<RadzenSecurityCode>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains("disabled", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
83
Radzen.Blazor.Tests/SelectBarTests.cs
Normal file
83
Radzen.Blazor.Tests/SelectBarTests.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SelectBarTests
|
||||
{
|
||||
[Fact]
|
||||
public void SelectBar_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSelectBar<int>>();
|
||||
|
||||
Assert.Contains(@"rz-selectbar", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectBar_Renders_Orientation()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSelectBar<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenSelectBarItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Option 1");
|
||||
builder.AddAttribute(2, "Value", 1);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
|
||||
Assert.Contains("rz-selectbar-horizontal", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
|
||||
Assert.Contains("rz-selectbar-vertical", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectBar_Renders_Multiple()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
// When Multiple is true, TValue should be IEnumerable<T>
|
||||
var component = ctx.RenderComponent<RadzenSelectBar<System.Collections.Generic.IEnumerable<int>>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Multiple, true);
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenSelectBarItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Option 1");
|
||||
builder.AddAttribute(2, "Value", 1);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
Assert.NotNull(component.Instance);
|
||||
Assert.True(component.Instance.Multiple);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SelectBar_Renders_Size()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSelectBar<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Items, builder =>
|
||||
{
|
||||
builder.OpenComponent<RadzenSelectBarItem>(0);
|
||||
builder.AddAttribute(1, "Text", "Option 1");
|
||||
builder.AddAttribute(2, "Value", 1);
|
||||
builder.CloseComponent();
|
||||
});
|
||||
});
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, ButtonSize.Small));
|
||||
Assert.Contains("rz-button-sm", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Size, ButtonSize.Large));
|
||||
Assert.Contains("rz-button-lg", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
65
Radzen.Blazor.Tests/SidebarToggleTests.cs
Normal file
65
Radzen.Blazor.Tests/SidebarToggleTests.cs
Normal file
@@ -0,0 +1,65 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SidebarToggleTests
|
||||
{
|
||||
[Fact]
|
||||
public void SidebarToggle_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSidebarToggle>();
|
||||
|
||||
Assert.Contains(@"rz-sidebar-toggle", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SidebarToggle_Renders_DefaultIcon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSidebarToggle>();
|
||||
|
||||
Assert.Contains("menu", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SidebarToggle_Renders_CustomIcon()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSidebarToggle>();
|
||||
|
||||
var icon = "close";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(icon, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SidebarToggle_Renders_AriaLabel()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSidebarToggle>();
|
||||
|
||||
var ariaLabel = "Toggle Navigation";
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ToggleAriaLabel, ariaLabel));
|
||||
|
||||
Assert.Contains($"aria-label=\"{ariaLabel}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SidebarToggle_Raises_ClickEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSidebarToggle>();
|
||||
|
||||
var clicked = false;
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Click, args => { clicked = true; }));
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
158
Radzen.Blazor.Tests/SkeletonTests.cs
Normal file
158
Radzen.Blazor.Tests/SkeletonTests.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using Bunit;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SkeletonTests
|
||||
{
|
||||
[Fact]
|
||||
public void Skeleton_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
Assert.Contains("rz-skeleton", component.Markup);
|
||||
Assert.Contains("rz-skeleton-text", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_Renders_TypeParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Variant, SkeletonVariant.Circular));
|
||||
|
||||
Assert.Contains("rz-skeleton", component.Markup);
|
||||
Assert.Contains("rz-skeleton-circular", component.Markup);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(SkeletonVariant.Text, "rz-skeleton-text")]
|
||||
[InlineData(SkeletonVariant.Circular, "rz-skeleton-circular")]
|
||||
[InlineData(SkeletonVariant.Rectangular, "rz-skeleton-rectangular")]
|
||||
public void Skeleton_Renders_AllTypes(SkeletonVariant type, string expectedClass)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>(parameters => parameters.Add(p => p.Variant, type));
|
||||
|
||||
Assert.Contains("rz-skeleton", component.Markup);
|
||||
Assert.Contains(expectedClass, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_Renders_AnimationParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Animation, SkeletonAnimation.Wave));
|
||||
|
||||
Assert.Contains("rz-skeleton", component.Markup);
|
||||
Assert.Contains("rz-skeleton-wave", component.Markup);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(SkeletonAnimation.Wave, "rz-skeleton-wave")]
|
||||
[InlineData(SkeletonAnimation.Pulse, "rz-skeleton-pulse")]
|
||||
public void Skeleton_Renders_AllAnimations(SkeletonAnimation animation, string expectedClass)
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>(parameters => parameters.Add(p => p.Animation, animation));
|
||||
|
||||
Assert.Contains("rz-skeleton", component.Markup);
|
||||
Assert.Contains(expectedClass, component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
var style = "width: 200px; height: 20px;";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, style));
|
||||
|
||||
Assert.Contains($"style=\"{style}\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_Renders_VisibleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
// Should be visible by default
|
||||
Assert.Contains("rz-skeleton", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Visible, false));
|
||||
|
||||
// Should not render when not visible
|
||||
Assert.DoesNotContain("rz-skeleton", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("data-testid", "skeleton-test"));
|
||||
|
||||
Assert.Contains("data-testid=\"skeleton-test\"", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_DefaultType_IsText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
// Should render with text type by default
|
||||
Assert.Contains("rz-skeleton-text", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skeleton_DefaultAnimation_IsNone()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSkeleton>();
|
||||
|
||||
// Should not render animation classes by default
|
||||
Assert.DoesNotContain("rz-skeleton-wave", component.Markup);
|
||||
Assert.DoesNotContain("rz-skeleton-pulse", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
159
Radzen.Blazor.Tests/SliderTests.cs
Normal file
159
Radzen.Blazor.Tests/SliderTests.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using Bunit;
|
||||
using Radzen.Blazor.Rendering;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SliderTests
|
||||
{
|
||||
[Fact]
|
||||
public void Slider_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
Assert.Contains(@$"rz-slider", component.Markup);
|
||||
Assert.Contains(@$"rz-slider-horizontal", component.Markup);
|
||||
Assert.Contains(@$"rz-slider-handle", component.Markup);
|
||||
Assert.Contains(@$"rz-slider-range rz-slider-range-min", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
decimal max = 100;
|
||||
var value = 4;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"style=""width: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
Assert.Contains(@$"style=""inset-inline-start: {Math.Round((value / max * 100)).ToInvariantString()}%;""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_ValueParameterWithRange()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<IEnumerable<int>>>(parameterBuilder => parameterBuilder.Add<bool>(p => p.Range, true));
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add<IEnumerable<int>>(p => p.Value, new int[] { 4, 30 });
|
||||
});
|
||||
|
||||
Assert.Contains(@$"inset-inline-start: 4%", component.Markup);
|
||||
Assert.Contains(@$"inset-inline-start: 30%", component.Markup);
|
||||
Assert.Contains(@$"inset-inline-start: 4%; width: 26%;", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_Orientation_Vertical()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Vertical);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-slider-vertical", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_Disabled()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Disabled, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_SliderHandle()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
Assert.Contains("rz-slider-handle", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_SliderRange()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
Assert.Contains("rz-slider-range", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Slider_Renders_TabIndex()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSlider<int>>();
|
||||
|
||||
Assert.Contains("tabindex=\"0\"", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
197
Radzen.Blazor.Tests/SpeechToTextButtonTests.cs
Normal file
197
Radzen.Blazor.Tests/SpeechToTextButtonTests.cs
Normal file
@@ -0,0 +1,197 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SpeechToTextButtonTests
|
||||
{
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Renders_Record_Button_When_Visible()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
component.Render();
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Does_Not_Renders_Record_Button_When_Visible_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Visible, false);
|
||||
});
|
||||
|
||||
Assert.Throws<ElementNotFoundException>(() => component.Find("button.rz-button-icon-only.rz-speech-to-text-button"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Renders_Additional_Css()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component =
|
||||
ctx.RenderComponent<RadzenSpeechToTextButton>(ComponentParameter.CreateParameter("class", "another-class"));
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button.another-class");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Can_Override_Default_Title_And_Aria_Label()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component =
|
||||
ctx.RenderComponent<RadzenSpeechToTextButton>(
|
||||
ComponentParameter.CreateParameter("title", "title override"),
|
||||
ComponentParameter.CreateParameter("aria-label", "aria-label override"));
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
Assert.Equal("title override", recordButton.GetAttribute("title"));
|
||||
Assert.Equal("aria-label override", recordButton.GetAttribute("aria-label"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Sets_Record_Button_Css_When_Record_Button_Clicked()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
component.Render();
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
|
||||
recordButton.Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var blinkingRecordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button-recording");
|
||||
|
||||
Assert.NotNull(blinkingRecordButton);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Sets_StopTitle_When_Record_Button_Clicked()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
component.Render();
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
|
||||
recordButton.Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var blinkingRecordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button-recording");
|
||||
|
||||
Assert.Equal(component.Instance.StopTitle, blinkingRecordButton.GetAttribute("title"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_ChangesIconWhen_When_Record_Button_Clicked()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
component.Render();
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
|
||||
recordButton.Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
var blinkingRecordButton = component.Find("button span");
|
||||
|
||||
Assert.Contains("stop", blinkingRecordButton.TextContent);
|
||||
Assert.DoesNotContain("mic", blinkingRecordButton.TextContent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_UnSets_Record_Button_Css_When_Record_Button_Clicked_Twice()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
component.Render();
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
|
||||
recordButton.Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
const string blinkingRecordButtonSelector = "button.rz-button-icon-only.rz-speech-to-text-button-recording";
|
||||
var blinkingRecordButton = component.Find(blinkingRecordButtonSelector);
|
||||
|
||||
Assert.NotNull(blinkingRecordButton);
|
||||
|
||||
blinkingRecordButton.Click();
|
||||
|
||||
component.Render();
|
||||
|
||||
Assert.Throws<ElementNotFoundException>(() => component.Find(blinkingRecordButtonSelector));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SpeechToTextButton_Invokes_OnResult_FromJs()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSpeechToTextButton>();
|
||||
|
||||
string resultsFromJs = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, r => resultsFromJs = r));
|
||||
|
||||
var recordButton = component.Find("button.rz-button-icon-only.rz-speech-to-text-button");
|
||||
|
||||
Assert.NotNull(recordButton);
|
||||
|
||||
recordButton.Click();
|
||||
|
||||
const string speechResults = "results from js";
|
||||
|
||||
component.InvokeAsync(() => component.Instance.OnResult(speechResults));
|
||||
|
||||
Assert.Equal(speechResults, resultsFromJs);
|
||||
}
|
||||
}
|
||||
}
|
||||
162
Radzen.Blazor.Tests/SplitButtonTests.cs
Normal file
162
Radzen.Blazor.Tests/SplitButtonTests.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using Bunit;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SplitButtonTests
|
||||
{
|
||||
[Fact]
|
||||
public void SplitButton_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_TextParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var text = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_IconParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Icon, icon));
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_IconAndTextParameters()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var text = "Test";
|
||||
var icon = "account_circle";
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Icon, icon);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<i class=""notranslate rz-button-icon-left rzi"">{icon}</i>", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_ImageParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var image = "test.png";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Image, image));
|
||||
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""image"" />", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_ImageAndTextParameters()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var text = "Test";
|
||||
var image = "test.png";
|
||||
|
||||
component.SetParametersAndRender(parameters => {
|
||||
parameters.Add(p => p.Text, text);
|
||||
parameters.Add(p => p.Image, image);
|
||||
parameters.Add(p => p.ImageAlternateText, text);
|
||||
});
|
||||
|
||||
Assert.Contains(@$"<img class=""notranslate rz-button-icon-left rzi"" src=""{image}"" alt=""{text}"" />", component.Markup);
|
||||
Assert.Contains(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_ButtonContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
RenderFragment buttonContent = (builder) => builder.AddMarkupContent(0, "<strong>Custom button content</strong>");
|
||||
|
||||
var text = "Test";
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>(parameters => parameters
|
||||
.Add(p => p.ButtonContent, buttonContent)
|
||||
.Add(p => p.Text, text));
|
||||
|
||||
Assert.Contains(@$"<strong>Custom button content</strong>", component.Markup);
|
||||
Assert.DoesNotContain(@$"<span class=""rz-button-text"">{text}</span>", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"rz-state-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SplitButton_Raises_ClickEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
ctx.JSInterop.Mode = JSRuntimeMode.Loose;
|
||||
ctx.JSInterop.SetupModule("_content/Radzen.Blazor/Radzen.Blazor.js");
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSplitButton>();
|
||||
|
||||
var clicked = false;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Click, args => { clicked = true; }));
|
||||
|
||||
component.Find("button").Click();
|
||||
|
||||
Assert.True(clicked);
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Radzen.Blazor.Tests/SplitterTests.cs
Normal file
42
Radzen.Blazor.Tests/SplitterTests.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SplitterTests
|
||||
{
|
||||
[Fact]
|
||||
public void Splitter_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSplitter>();
|
||||
|
||||
Assert.Contains(@"rz-splitter", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Splitter_Renders_Orientation_Horizontal()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSplitter>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Horizontal);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-splitter-horizontal", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Splitter_Renders_Orientation_Vertical()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSplitter>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.Orientation, Orientation.Vertical);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-splitter-vertical", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
98
Radzen.Blazor.Tests/StackTests.cs
Normal file
98
Radzen.Blazor.Tests/StackTests.cs
Normal file
@@ -0,0 +1,98 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class StackTests
|
||||
{
|
||||
[Fact]
|
||||
public void Stack_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
Assert.Contains(@"rz-stack", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_ChildContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>(parameters =>
|
||||
{
|
||||
parameters.AddChildContent("<div>Stack Content</div>");
|
||||
});
|
||||
|
||||
Assert.Contains("Stack Content", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_Orientation()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Horizontal));
|
||||
Assert.Contains("rz-flex-row", component.Markup);
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Orientation, Orientation.Vertical));
|
||||
Assert.Contains("rz-flex-column", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_Gap()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Gap, "1.5rem"));
|
||||
|
||||
Assert.Contains("--rz-gap:1.5rem", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_AlignItems()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.AlignItems, AlignItems.Center));
|
||||
|
||||
Assert.Contains("rz-align-items-center", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_JustifyContent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.JustifyContent, JustifyContent.SpaceBetween));
|
||||
|
||||
Assert.Contains("rz-justify-content-space-between", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_Wrap()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Wrap, FlexWrap.Wrap));
|
||||
|
||||
Assert.Contains("flex-wrap:wrap", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Stack_Renders_Reverse()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenStack>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Reverse, true));
|
||||
|
||||
Assert.Contains("rz-flex-column-reverse", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
70
Radzen.Blazor.Tests/StepsTests.cs
Normal file
70
Radzen.Blazor.Tests/StepsTests.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class StepsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Steps_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSteps>();
|
||||
|
||||
Assert.Contains(@"rz-steps", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Steps_Renders_ShowStepsButtons_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowStepsButtons, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-steps-buttons", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Steps_Renders_ShowStepsButtons_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowStepsButtons, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-steps-buttons", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Steps_Renders_StepsButtons()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowStepsButtons, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-steps-prev", component.Markup);
|
||||
Assert.Contains("rz-steps-next", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Steps_Renders_CustomButtonText()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenSteps>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.ShowStepsButtons, true);
|
||||
parameters.Add(p => p.NextText, "Continue");
|
||||
parameters.Add(p => p.PreviousText, "Back");
|
||||
});
|
||||
|
||||
Assert.Contains("Continue", component.Markup);
|
||||
Assert.Contains("Back", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
151
Radzen.Blazor.Tests/SwitchTests.cs
Normal file
151
Radzen.Blazor.Tests/SwitchTests.cs
Normal file
@@ -0,0 +1,151 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class SwitchTests
|
||||
{
|
||||
[Fact]
|
||||
public void Switch_Renders_CssClass()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
Assert.Contains(@$"rz-switch", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_ValueParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
var value = true;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Value, value));
|
||||
|
||||
Assert.Contains(@$"rz-switch-checked", component.Markup);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_StyleParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
var value = "width:20px";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Style, value));
|
||||
|
||||
Assert.Contains(@$"style=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_NameParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
var value = "Test";
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Name, value));
|
||||
|
||||
Assert.Contains(@$"name=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_TabIndexParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
var value = 1;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<int>(p => p.TabIndex, value));
|
||||
|
||||
Assert.Contains(@$"tabindex=""{value}""", component.Markup);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_DisabledParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.Disabled, true));
|
||||
|
||||
Assert.Contains(@$"rz-disabled", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_UnmatchedParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.AddUnmatched("autofocus", ""));
|
||||
|
||||
Assert.Contains(@$"autofocus", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Raises_ChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
var raised = false;
|
||||
var value = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.Change, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("div").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, !(bool)newValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Raises_ValueChangedEvent()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
var raised = false;
|
||||
var value = false;
|
||||
object newValue = null;
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add(p => p.ValueChanged, args => { raised = true; newValue = args; }));
|
||||
|
||||
component.Find("div").Click();
|
||||
|
||||
Assert.True(raised);
|
||||
Assert.True(object.Equals(value, !(bool)newValue));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Switch_Renders_ReadOnlyParameter()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
|
||||
var component = ctx.RenderComponent<RadzenSwitch>();
|
||||
|
||||
component.SetParametersAndRender(parameters => parameters.Add<bool>(p => p.ReadOnly, true));
|
||||
|
||||
Assert.Contains(@$"rz-readonly", component.Markup);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
100
Radzen.Blazor.Tests/TableTests.cs
Normal file
100
Radzen.Blazor.Tests/TableTests.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class TableTests
|
||||
{
|
||||
[Fact]
|
||||
public void Table_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>();
|
||||
|
||||
Assert.Contains(@"rz-datatable", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_TableElement()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>();
|
||||
|
||||
Assert.Contains("rz-grid-table", component.Markup);
|
||||
Assert.Contains("<table", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_GridLines_None()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.GridLines, DataGridGridLines.None);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-grid-gridlines-none", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_GridLines_Horizontal()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.GridLines, DataGridGridLines.Horizontal);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-grid-gridlines-horizontal", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_GridLines_Vertical()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.GridLines, DataGridGridLines.Vertical);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-grid-gridlines-vertical", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_GridLines_Both()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.GridLines, DataGridGridLines.Both);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-grid-gridlines-both", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_AllowAlternatingRows_True()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowAlternatingRows, true);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-grid-table-striped", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Table_Renders_AllowAlternatingRows_False()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTable>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.AllowAlternatingRows, false);
|
||||
});
|
||||
|
||||
Assert.DoesNotContain("rz-grid-table-striped", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
108
Radzen.Blazor.Tests/TabsTests.cs
Normal file
108
Radzen.Blazor.Tests/TabsTests.cs
Normal file
@@ -0,0 +1,108 @@
|
||||
using Bunit;
|
||||
using Xunit;
|
||||
|
||||
namespace Radzen.Blazor.Tests
|
||||
{
|
||||
public class TabsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Tabs_Renders_WithClassName()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>();
|
||||
|
||||
Assert.Contains(@"rz-tabview", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPosition_Top()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TabPosition, TabPosition.Top);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-tabview-top", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPosition_Bottom()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TabPosition, TabPosition.Bottom);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-tabview-bottom", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPosition_Left()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TabPosition, TabPosition.Left);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-tabview-left", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPosition_Right()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TabPosition, TabPosition.Right);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-tabview-right", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPosition_TopRight()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TabPosition, TabPosition.TopRight);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-tabview-top-right", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPosition_BottomRight()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>(parameters =>
|
||||
{
|
||||
parameters.Add(p => p.TabPosition, TabPosition.BottomRight);
|
||||
});
|
||||
|
||||
Assert.Contains("rz-tabview-bottom-right", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabNav()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>();
|
||||
|
||||
Assert.Contains("rz-tabview-nav", component.Markup);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Tabs_Renders_TabPanels()
|
||||
{
|
||||
using var ctx = new TestContext();
|
||||
var component = ctx.RenderComponent<RadzenTabs>();
|
||||
|
||||
Assert.Contains("rz-tabview-panels", component.Markup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
Radzen.Blazor.Tests/Temperature.cs
Normal file
35
Radzen.Blazor.Tests/Temperature.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Radzen.Blazor.Tests;
|
||||
|
||||
public record struct Temperature(decimal DegreesCelsius)
|
||||
: IFormattable
|
||||
{
|
||||
public decimal Celsius => DegreesCelsius;
|
||||
public decimal Fahrenheit => DegreesCelsius * 9 / 5 + 32;
|
||||
public decimal Kelvin => DegreesCelsius + 273.15m;
|
||||
|
||||
public override string ToString() => ToString("G");
|
||||
public string ToString(string format) => ToString(format, CultureInfo.CurrentCulture);
|
||||
|
||||
public string ToString(string format, IFormatProvider provider)
|
||||
{
|
||||
provider ??= CultureInfo.CurrentCulture;
|
||||
if (string.IsNullOrEmpty(format))
|
||||
format = "G";
|
||||
|
||||
switch (format.ToUpperInvariant())
|
||||
{
|
||||
case "G":
|
||||
case "C":
|
||||
return $"{Celsius.ToString("F2", provider)} °C";
|
||||
case "F":
|
||||
return $"{Fahrenheit.ToString("F2", provider)} °F";
|
||||
case "K":
|
||||
return $"{Kelvin.ToString("F2", provider)} K";
|
||||
default:
|
||||
throw new FormatException($"The {format} format string is not supported.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user