Compare commits
1016 Commits
master-bet
...
release/20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
abeffb2a19 | ||
|
|
70058b6bd4 | ||
|
|
67c63f81d9 | ||
|
|
fb8452b2bb | ||
|
|
1f281e8439 | ||
|
|
223c705e8f | ||
|
|
00d8b533f4 | ||
|
|
3b25a8fe07 | ||
|
|
a57b9cddb5 | ||
|
|
064ed1bb8b | ||
|
|
efda254981 | ||
|
|
3fa6b8b6ac | ||
|
|
4603643240 | ||
|
|
f82b02958f | ||
|
|
5d1f61753b | ||
|
|
883043cde3 | ||
|
|
85ce7c638d | ||
|
|
547e279693 | ||
|
|
b9bdefe898 | ||
|
|
c963cb6fcc | ||
|
|
fa6d4cce2a | ||
|
|
c7188d5a71 | ||
|
|
c333d72743 | ||
|
|
2a1ec4eff3 | ||
|
|
190b2e5b5c | ||
|
|
3e2a517272 | ||
|
|
a6cd35bd06 | ||
|
|
ba3032e553 | ||
|
|
20fd452335 | ||
|
|
8f83a5f5e6 | ||
|
|
4e417d1b10 | ||
|
|
3ee63a503a | ||
|
|
8dd0e12398 | ||
|
|
253b4d0ddc | ||
|
|
a8b0931659 | ||
|
|
11a182c68a | ||
|
|
2583d21cf1 | ||
|
|
aa6032d74f | ||
|
|
e1bac5fe9f | ||
|
|
0c74848c54 | ||
|
|
1c4f2d2de0 | ||
|
|
d67d2aa064 | ||
|
|
208f3281a9 | ||
|
|
fb7e3bc812 | ||
|
|
884adb963c | ||
|
|
29c4df9f76 | ||
|
|
f1940a320c | ||
|
|
a297bba193 | ||
|
|
375a3fe386 | ||
|
|
d837754ef6 | ||
|
|
49a1f0c42c | ||
|
|
a5033e10cd | ||
|
|
00f0952ab2 | ||
|
|
ec5b636c26 | ||
|
|
7126cc0d56 | ||
|
|
568d8887ce | ||
|
|
4927e84a88 | ||
|
|
d2d8039cb9 | ||
|
|
5da242d785 | ||
|
|
87f25b1ed4 | ||
|
|
4f9afc8578 | ||
|
|
defadf70e3 | ||
|
|
82be3853f0 | ||
|
|
ff184926fc | ||
|
|
0e9768c0f6 | ||
|
|
805c924a15 | ||
|
|
10ff8fc432 | ||
|
|
e2db0bab9f | ||
|
|
92ee5169ab | ||
|
|
5cf2345dca | ||
|
|
0accf6a18f | ||
|
|
52e46aad86 | ||
|
|
43f49e5e51 | ||
|
|
60908b123d | ||
|
|
5169fd178a | ||
|
|
bbc446ef01 | ||
|
|
65bb8c6f26 | ||
|
|
171f40819c | ||
|
|
4baa26cb25 | ||
|
|
01da7fde31 | ||
|
|
3c8234d715 | ||
|
|
866f242465 | ||
|
|
f690596825 | ||
|
|
5f494e4b78 | ||
|
|
7b814329da | ||
|
|
2fc0e1cf50 | ||
|
|
ba3f98aeb4 | ||
|
|
f49818ade3 | ||
|
|
b37c70494b | ||
|
|
ff1db26f41 | ||
|
|
3550c97966 | ||
|
|
956c686360 | ||
|
|
508b0d7711 | ||
|
|
abb1464e30 | ||
|
|
704d5415d6 | ||
|
|
6cc1cfd1b0 | ||
|
|
e6455a7fd3 | ||
|
|
a9aad2a751 | ||
|
|
1bf745345d | ||
|
|
63c71ed923 | ||
|
|
3a844aefa0 | ||
|
|
4a16df36dd | ||
|
|
93c92e8976 | ||
|
|
9523e5534d | ||
|
|
d20048026c | ||
|
|
7ba3ed2b89 | ||
|
|
2cc0b7d741 | ||
|
|
97693fbcff | ||
|
|
5e94b1a71e | ||
|
|
970275e62a | ||
|
|
15c7b6f1c8 | ||
|
|
aa076da255 | ||
|
|
3dd154de79 | ||
|
|
72a2366abe | ||
|
|
36f517e8e1 | ||
|
|
981fb57d36 | ||
|
|
3149c3cfc6 | ||
|
|
a059c2b5a8 | ||
|
|
f91e0ec39f | ||
|
|
c31d4096c6 | ||
|
|
118f14ed4c | ||
|
|
207bb39672 | ||
|
|
0d0791cc41 | ||
|
|
16e34e4ed9 | ||
|
|
cd04f2b2b2 | ||
|
|
26e164b4d1 | ||
|
|
f45aa69917 | ||
|
|
4b44ff29ee | ||
|
|
f15f5d7309 | ||
|
|
ae6b2fe4f5 | ||
|
|
4ca686126a | ||
|
|
ea55b1a797 | ||
|
|
668366e886 | ||
|
|
eb1b2aef55 | ||
|
|
906430add5 | ||
|
|
f8fbbd2323 | ||
|
|
adab6ef0c6 | ||
|
|
ddfd91617f | ||
|
|
8418b4cb91 | ||
|
|
e593943d99 | ||
|
|
b58b5e65dc | ||
|
|
6d393987e8 | ||
|
|
c254a8abfe | ||
|
|
852231b503 | ||
|
|
f864e40a90 | ||
|
|
802f70dde8 | ||
|
|
6cb4fd6b93 | ||
|
|
70ca6edcb2 | ||
|
|
9dcc861740 | ||
|
|
fecb7fb24b | ||
|
|
c5b94db8af | ||
|
|
6690c9c692 | ||
|
|
506edcb3c6 | ||
|
|
c45e53e38b | ||
|
|
d8d8a4701e | ||
|
|
970c4ee9e1 | ||
|
|
c2386f43ef | ||
|
|
870878d151 | ||
|
|
cdf7bcf839 | ||
|
|
0fd3e75862 | ||
|
|
fcd3234fd9 | ||
|
|
2afa810e6c | ||
|
|
ff33b924b2 | ||
|
|
8a4fee7aea | ||
|
|
fa578efee4 | ||
|
|
4b6b4c0c63 | ||
|
|
8199ab83ef | ||
|
|
8e50d0ba53 | ||
|
|
7d72d66a97 | ||
|
|
3454694887 | ||
|
|
2a51c8a2bf | ||
|
|
524f623fd4 | ||
|
|
7ab7e18d96 | ||
|
|
6f2c8dba5a | ||
|
|
162d8bfffe | ||
|
|
61569d97cb | ||
|
|
975622a31c | ||
|
|
7524d06126 | ||
|
|
7f75eeadb9 | ||
|
|
4db2b73397 | ||
|
|
84bb25985b | ||
|
|
2f493c63f8 | ||
|
|
2761356f02 | ||
|
|
e38a58550f | ||
|
|
25ef4c6228 | ||
|
|
8207a52b6b | ||
|
|
8bbe7a1f0f | ||
|
|
2b052b3d43 | ||
|
|
94e7bf3f92 | ||
|
|
277fbeebc8 | ||
|
|
64e3f5f2ac | ||
|
|
399df78957 | ||
|
|
294325343b | ||
|
|
ed17eec948 | ||
|
|
f87c95079c | ||
|
|
327149ffc9 | ||
|
|
f81b21b933 | ||
|
|
a559b56983 | ||
|
|
6a9030b653 | ||
|
|
bb7f7deb50 | ||
|
|
55c10890bd | ||
|
|
fc7da187f4 | ||
|
|
edef0b194d | ||
|
|
f593f83ec1 | ||
|
|
5752f123ac | ||
|
|
37f0c98e75 | ||
|
|
6396d68584 | ||
|
|
bfd29f25dd | ||
|
|
e75e35e4ee | ||
|
|
48f18514af | ||
|
|
d7ddbf7e8d | ||
|
|
1b0198af63 | ||
|
|
ace16ba873 | ||
|
|
76c13700be | ||
|
|
f57a4bd948 | ||
|
|
8ae8737fe2 | ||
|
|
fef4393f9c | ||
|
|
47adb6d40a | ||
|
|
4940b10910 | ||
|
|
9c8e241ef7 | ||
|
|
36f7b7a1a1 | ||
|
|
c3d6b98c89 | ||
|
|
4b49654083 | ||
|
|
78223078f4 | ||
|
|
ca4b78d44c | ||
|
|
b0a5f2d998 | ||
|
|
19c980bc3b | ||
|
|
78d6b9699b | ||
|
|
82d8cb22df | ||
|
|
d7bfc789e2 | ||
|
|
b54d0ed62a | ||
|
|
8386443cb0 | ||
|
|
9c41af82d7 | ||
|
|
2997dd4e4d | ||
|
|
4602648fe5 | ||
|
|
a8f2ca5643 | ||
|
|
7959dc67ce | ||
|
|
0d2cdec75c | ||
|
|
cd055f7344 | ||
|
|
a4116b6c28 | ||
|
|
269ef25ece | ||
|
|
c43709395f | ||
|
|
575fbd5357 | ||
|
|
10f60752c8 | ||
|
|
870f8463db | ||
|
|
2ad887fb82 | ||
|
|
40a1a86f72 | ||
|
|
5567a69142 | ||
|
|
95d43d936c | ||
|
|
9f56568680 | ||
|
|
762fec1d9a | ||
|
|
3428940c72 | ||
|
|
ea604a5e64 | ||
|
|
0946b0d3a3 | ||
|
|
5b76473cbc | ||
|
|
db5359e086 | ||
|
|
976dd2cbfb | ||
|
|
35046f11c2 | ||
|
|
f4c4005a2a | ||
|
|
b6956b3649 | ||
|
|
69d8d27ad3 | ||
|
|
6cf4a50a83 | ||
|
|
755acd24f0 | ||
|
|
b2b4902d23 | ||
|
|
079d6cfee6 | ||
|
|
6f69129829 | ||
|
|
3e3b3c269a | ||
|
|
39f1af7d4b | ||
|
|
1ea4d616d7 | ||
|
|
fdf0ecf6f6 | ||
|
|
d846894d22 | ||
|
|
7d3101c877 | ||
|
|
e5f7285253 | ||
|
|
e46c304f7c | ||
|
|
c3f0e6f10c | ||
|
|
1aa570db90 | ||
|
|
1c2be3c890 | ||
|
|
05e4eacf34 | ||
|
|
d0da2dd66c | ||
|
|
e1417b03f9 | ||
|
|
7b99de8046 | ||
|
|
877b3ab39c | ||
|
|
6dc03d7f67 | ||
|
|
2a5e6a51aa | ||
|
|
885477fa68 | ||
|
|
8f031a78c1 | ||
|
|
c7db792793 | ||
|
|
31be51ef79 | ||
|
|
e4066c1570 | ||
|
|
69b36a4c34 | ||
|
|
c7b8df5655 | ||
|
|
d85768b2ac | ||
|
|
ec480f2cb1 | ||
|
|
a569c1f4f9 | ||
|
|
f5b30c9376 | ||
|
|
412508fbcf | ||
|
|
dbfd9bce54 | ||
|
|
07a8e5b216 | ||
|
|
38bf58c613 | ||
|
|
ba90d72d55 | ||
|
|
9889bee924 | ||
|
|
a19e4e8f16 | ||
|
|
5121852fbc | ||
|
|
52e0558c79 | ||
|
|
1d1ff5d20b | ||
|
|
ec00697d31 | ||
|
|
c25714b68e | ||
|
|
562d0b8641 | ||
|
|
dc0147c5f9 | ||
|
|
296afdbeee | ||
|
|
d48d6cdd91 | ||
|
|
9363790541 | ||
|
|
2bceba948d | ||
|
|
2f8f058c5c | ||
|
|
168d4246af | ||
|
|
133d593689 | ||
|
|
cdf6050ec2 | ||
|
|
68784018e6 | ||
|
|
19dfec2a34 | ||
|
|
55d729339f | ||
|
|
c3108a17f4 | ||
|
|
d47ae64bd6 | ||
|
|
5206ba7a74 | ||
|
|
f451155689 | ||
|
|
9f06e19346 | ||
|
|
f4be3e9668 | ||
|
|
095e1e9789 | ||
|
|
a0b9f99dd3 | ||
|
|
a33a92207b | ||
|
|
ee613db0cb | ||
|
|
55b892a74e | ||
|
|
16754d9657 | ||
|
|
33db67122c | ||
|
|
b9b88b0e23 | ||
|
|
992ad71910 | ||
|
|
51d1f926c2 | ||
|
|
c70447f337 | ||
|
|
dc367e1a30 | ||
|
|
f647e1ff11 | ||
|
|
ee7997ffbc | ||
|
|
2dbb5adbbb | ||
|
|
cc9f342575 | ||
|
|
252262f4a7 | ||
|
|
f77a16648f | ||
|
|
d6e3c54b68 | ||
|
|
7294e96a77 | ||
|
|
a4f4f45251 | ||
|
|
acc91abc0c | ||
|
|
18d5176cb9 | ||
|
|
d6d6ced7a4 | ||
|
|
52809cc849 | ||
|
|
c525b7ea3f | ||
|
|
e799417aaf | ||
|
|
ef077c2d48 | ||
|
|
e78b114544 | ||
|
|
df170ddd27 | ||
|
|
17928741e3 | ||
|
|
a6b825ffdf | ||
|
|
0d3bc0e95f | ||
|
|
0f62a2d73d | ||
|
|
bcdd32f92f | ||
|
|
6865fcbffc | ||
|
|
8e623c71a9 | ||
|
|
1e06502464 | ||
|
|
f2914868e2 | ||
|
|
561f0313f9 | ||
|
|
1e27c4e1ae | ||
|
|
46676ba8eb | ||
|
|
02a49efbea | ||
|
|
5f2a5e1025 | ||
|
|
42552e4f4f | ||
|
|
f2af78f056 | ||
|
|
269d55bde3 | ||
|
|
71f3dbbeb4 | ||
|
|
73dfb74ed7 | ||
|
|
7dd6baef33 | ||
|
|
519b532091 | ||
|
|
4fb9c37c0d | ||
|
|
c9b63be29f | ||
|
|
84bc735dce | ||
|
|
a44b9417a1 | ||
|
|
6b157ed43c | ||
|
|
9050276ea7 | ||
|
|
683293d042 | ||
|
|
70d009ab49 | ||
|
|
dbc2d10d6d | ||
|
|
059b854db9 | ||
|
|
13569a1785 | ||
|
|
6fd70b165b | ||
|
|
11d94cf286 | ||
|
|
c98a48ea14 | ||
|
|
b8fa80419b | ||
|
|
2a8846297f | ||
|
|
fb322f760f | ||
|
|
0b9f718106 | ||
|
|
57b3b3a9cd | ||
|
|
6513432993 | ||
|
|
80a564d4b6 | ||
|
|
132ecffc40 | ||
|
|
cdf02a8eac | ||
|
|
7d22dcab7c | ||
|
|
45c943a78f | ||
|
|
cf82a8013f | ||
|
|
25d145d864 | ||
|
|
7822e3f90e | ||
|
|
a4a612fbe4 | ||
|
|
07da472e82 | ||
|
|
e9096632a4 | ||
|
|
6475a8bdce | ||
|
|
535f92b7d2 | ||
|
|
00b91616f5 | ||
|
|
b8c34762ed | ||
|
|
9f92347936 | ||
|
|
b657a893ad | ||
|
|
387670212a | ||
|
|
b8e42544ae | ||
|
|
bcea47c2c6 | ||
|
|
b38aaba56c | ||
|
|
8099607d90 | ||
|
|
2d9412e4e8 | ||
|
|
069d508528 | ||
|
|
d68ce67e4f | ||
|
|
a9d38e743f | ||
|
|
878e81dc8f | ||
|
|
5ccf74f99c | ||
|
|
6c823f4914 | ||
|
|
de35155ffe | ||
|
|
470eb19a2f | ||
|
|
947bc33946 | ||
|
|
8bcaabfb57 | ||
|
|
a1f7e7b755 | ||
|
|
c8f8a86a98 | ||
|
|
bb205af019 | ||
|
|
443c6046f9 | ||
|
|
1620b94a7b | ||
|
|
81f94eac6c | ||
|
|
ffada75d9e | ||
|
|
34d773bcd8 | ||
|
|
ec7509670d | ||
|
|
eceac11af2 | ||
|
|
dd64598850 | ||
|
|
650ace6be6 | ||
|
|
1c71a5c5e0 | ||
|
|
9c699a634b | ||
|
|
a47d17bbf5 | ||
|
|
164f67d6ce | ||
|
|
465b9e7177 | ||
|
|
f5a914c318 | ||
|
|
de486d2e73 | ||
|
|
d7f946ec2a | ||
|
|
4d1480bb61 | ||
|
|
25a49473f9 | ||
|
|
8e86e7fba5 | ||
|
|
f9b380a0d4 | ||
|
|
f664a56b16 | ||
|
|
0acfd3c4b1 | ||
|
|
bfc4cb1ad9 | ||
|
|
66dd1a9a2b | ||
|
|
1f42be2e54 | ||
|
|
30d344af6b | ||
|
|
3ca989fd8c | ||
|
|
73c38b3ae4 | ||
|
|
08749b0c92 | ||
|
|
ea73af371e | ||
|
|
ce2086a480 | ||
|
|
63f7106d2b | ||
|
|
8cce6ea6e3 | ||
|
|
77c486b4c9 | ||
|
|
7c8f276bb0 | ||
|
|
e991586254 | ||
|
|
d61ab796a7 | ||
|
|
e634369975 | ||
|
|
453236cf3a | ||
|
|
3530476b07 | ||
|
|
e75d8d1874 | ||
|
|
719fa6a67d | ||
|
|
148cd43c5d | ||
|
|
3d753a2d19 | ||
|
|
693d02de87 | ||
|
|
80b4ef3ae8 | ||
|
|
6b9269eb2d | ||
|
|
15c9529885 | ||
|
|
512cd70d13 | ||
|
|
e5599ff4c4 | ||
|
|
32041ee3fc | ||
|
|
07bf84ed69 | ||
|
|
0c0449aa17 | ||
|
|
26cb527d37 | ||
|
|
33c282051b | ||
|
|
df0f8ef9dc | ||
|
|
e23f13a1b3 | ||
|
|
f5b8bf1d74 | ||
|
|
61766017ea | ||
|
|
706984a53b | ||
|
|
e137feca20 | ||
|
|
9e66d7c929 | ||
|
|
9605bf5c21 | ||
|
|
c2cc7b1e9e | ||
|
|
fe55eccbf9 | ||
|
|
47e17dc78a | ||
|
|
88a71dd647 | ||
|
|
ce0b3a8635 | ||
|
|
b8e4520366 | ||
|
|
bd3d86a6dd | ||
|
|
c3b395c99e | ||
|
|
a2a7c1c58c | ||
|
|
eb4e5d9576 | ||
|
|
1469960643 | ||
|
|
19a03ec080 | ||
|
|
33d5d9b462 | ||
|
|
b5a371d0cf | ||
|
|
b61fd17879 | ||
|
|
6722f8b1e5 | ||
|
|
69ff75157d | ||
|
|
7fad968ad2 | ||
|
|
7c619f5439 | ||
|
|
3b35f38ad5 | ||
|
|
096017c3d6 | ||
|
|
4ff2ab1bc8 | ||
|
|
ef698529d7 | ||
|
|
167d5bd89a | ||
|
|
c328a55453 | ||
|
|
83a976e98f | ||
|
|
d004133ad6 | ||
|
|
d7caaecaf7 | ||
|
|
96242a555a | ||
|
|
7ece1256f2 | ||
|
|
1f5c1b9658 | ||
|
|
a43134511b | ||
|
|
b188cce3ea | ||
|
|
56dfd174dd | ||
|
|
39d4f56812 | ||
|
|
f85e3d8d60 | ||
|
|
c33eaa6c68 | ||
|
|
c4d39cf3d3 | ||
|
|
532cd4937b | ||
|
|
926c13569d | ||
|
|
cbf5c5729f | ||
|
|
5e63ce7271 | ||
|
|
91bc73baf2 | ||
|
|
ab031c01de | ||
|
|
e51f72ff98 | ||
|
|
3eb010285d | ||
|
|
37196e65c3 | ||
|
|
5c0f228876 | ||
|
|
2b172f9999 | ||
|
|
0803f5af35 | ||
|
|
69ac2f0a6c | ||
|
|
0c842e0e15 | ||
|
|
d94678d4f4 | ||
|
|
b20c605c85 | ||
|
|
d8ac708536 | ||
|
|
8a32fe50f3 | ||
|
|
7897a490bd | ||
|
|
17d73fc6d7 | ||
|
|
90814f41a2 | ||
|
|
7d1910086e | ||
|
|
282dbd0913 | ||
|
|
46def33bc8 | ||
|
|
fc41226404 | ||
|
|
a51e088f69 | ||
|
|
3683bc161d | ||
|
|
817c41afb9 | ||
|
|
04315a9045 | ||
|
|
d0871ffe21 | ||
|
|
1343b68cc6 | ||
|
|
dca587d6e0 | ||
|
|
72aece7f14 | ||
|
|
ae07f71e76 | ||
|
|
a3d6d44089 | ||
|
|
07a18bcd8c | ||
|
|
9b9ac505e9 | ||
|
|
8f7e2bd9d3 | ||
|
|
19ec4cb021 | ||
|
|
a7aa2a31a6 | ||
|
|
346e82bdbc | ||
|
|
fd9575e5a5 | ||
|
|
54dc9c8587 | ||
|
|
9f9fa3b952 | ||
|
|
3acf271dcf | ||
|
|
af6bc0fb5a | ||
|
|
cc7c98336f | ||
|
|
d0e289757f | ||
|
|
becc54f7b3 | ||
|
|
e3fabdac91 | ||
|
|
40621db556 | ||
|
|
dc22b96bed | ||
|
|
c3fa4ef8af | ||
|
|
0a784c6873 | ||
|
|
e1df64d592 | ||
|
|
b161530381 | ||
|
|
ae9e9f4b72 | ||
|
|
136ef63c14 | ||
|
|
c2e64a124d | ||
|
|
1fa83d124d | ||
|
|
b1dfd23fd4 | ||
|
|
3eaa23beac | ||
|
|
090c55fb3d | ||
|
|
bf5d1b69d4 | ||
|
|
7f930fcd5b | ||
|
|
301c680bff | ||
|
|
595159f24d | ||
|
|
cc734d3981 | ||
|
|
2ace0189bc | ||
|
|
b41d69593d | ||
|
|
248aa65195 | ||
|
|
b7055aac84 | ||
|
|
3bf1ec25c1 | ||
|
|
815ada0516 | ||
|
|
98b14f2a5b | ||
|
|
bfa5cdcede | ||
|
|
37b251a514 | ||
|
|
9c6e514db0 | ||
|
|
b83a39dc4a | ||
|
|
0ea422ab7c | ||
|
|
09e505399c | ||
|
|
80b9b5fbf6 | ||
|
|
40c801592d | ||
|
|
42f9f275c7 | ||
|
|
15a9988894 | ||
|
|
39b119b2e8 | ||
|
|
21a724fbf1 | ||
|
|
d6e27c7ced | ||
|
|
5bc224206c | ||
|
|
190da863c2 | ||
|
|
2711b5fce5 | ||
|
|
8e9358cd6f | ||
|
|
0e31bbb789 | ||
|
|
3b635aeed3 | ||
|
|
32a98ed438 | ||
|
|
9b060b272c | ||
|
|
cd9e67c9df | ||
|
|
1f896b1ede | ||
|
|
23f9f8fa20 | ||
|
|
5bb8286301 | ||
|
|
9012e4deec | ||
|
|
568e74b21f | ||
|
|
8d729f1e83 | ||
|
|
6463e13eeb | ||
|
|
ab2323e5c1 | ||
|
|
f31ae9ac6d | ||
|
|
6831a79407 | ||
|
|
27c24619c3 | ||
|
|
38aef71269 | ||
|
|
e162460b9c | ||
|
|
c55374edc8 | ||
|
|
b1ca09bd4f | ||
|
|
f9ca36ec89 | ||
|
|
9d479d4b4d | ||
|
|
23b5b740cb | ||
|
|
8f9b05b974 | ||
|
|
d1132e7d45 | ||
|
|
922ba4939e | ||
|
|
c2a4e75005 | ||
|
|
926ff3cb6f | ||
|
|
960b0b4d09 | ||
|
|
f35ea026b8 | ||
|
|
c28d5b664d | ||
|
|
5fcf9712be | ||
|
|
f05d909a5c | ||
|
|
a429756823 | ||
|
|
8460a99085 | ||
|
|
8cb18d6d1d | ||
|
|
cdd5b26443 | ||
|
|
01a9e7dc34 | ||
|
|
2ea3a10c8b | ||
|
|
214e29d292 | ||
|
|
f618719419 | ||
|
|
1b16d75dc7 | ||
|
|
a6497bb14e | ||
|
|
8ea7db6488 | ||
|
|
b1fc2828c8 | ||
|
|
bc25c23982 | ||
|
|
2604507403 | ||
|
|
737c4164c4 | ||
|
|
85f973f5e6 | ||
|
|
f855e6423e | ||
|
|
0ae9bb7e64 | ||
|
|
2215c8439e | ||
|
|
ec517a0fc3 | ||
|
|
f98c9e6f71 | ||
|
|
f279fc1e81 | ||
|
|
7e01f667b3 | ||
|
|
f61b89f213 | ||
|
|
940f77bf86 | ||
|
|
5623497e32 | ||
|
|
d9d30b59f0 | ||
|
|
53a55dd1ef | ||
|
|
1ae2133d23 | ||
|
|
9daf992582 | ||
|
|
63945e0ce2 | ||
|
|
d9020de77b | ||
|
|
55ef205907 | ||
|
|
42aa42c892 | ||
|
|
2d07c20ea8 | ||
|
|
8b0b37aab4 | ||
|
|
6640ed629d | ||
|
|
f190c26311 | ||
|
|
48a007de3c | ||
|
|
af7ff2d8b5 | ||
|
|
3e44458f5c | ||
|
|
3687a644d6 | ||
|
|
2fe4b113b2 | ||
|
|
1d04683c06 | ||
|
|
04a06e85ec | ||
|
|
9346a819f5 | ||
|
|
4eb8faa5d9 | ||
|
|
3b54fd27bb | ||
|
|
0c2396eb12 | ||
|
|
232109c2c7 | ||
|
|
d5198edfc0 | ||
|
|
39bba3623a | ||
|
|
62dac2193f | ||
|
|
72da0734c8 | ||
|
|
69b4b76501 | ||
|
|
ae56e27e5f | ||
|
|
d6bb6a891d | ||
|
|
2f83b0baa7 | ||
|
|
04728690ca | ||
|
|
2a31d740d5 | ||
|
|
1718ba5695 | ||
|
|
2826360627 | ||
|
|
3690ea0332 | ||
|
|
ff7523ecb8 | ||
|
|
b53fdadaee | ||
|
|
93390bef63 | ||
|
|
485e2ef4f1 | ||
|
|
9de3b5efb6 | ||
|
|
2632282bba | ||
|
|
7379f50792 | ||
|
|
9ae53d090f | ||
|
|
677c7bb4cc | ||
|
|
4fdc241b9c | ||
|
|
06ca7603b9 | ||
|
|
28dc4867db | ||
|
|
1cf13da413 | ||
|
|
3919efaa77 | ||
|
|
a76fc780cb | ||
|
|
d915c123db | ||
|
|
151c9c0add | ||
|
|
f14dc497cf | ||
|
|
89339e1033 | ||
|
|
146a61c9cf | ||
|
|
5250d97935 | ||
|
|
18dce9795d | ||
|
|
7add2bb12e | ||
|
|
756fc07193 | ||
|
|
71a5722b0e | ||
|
|
4507135a1b | ||
|
|
7f2479f597 | ||
|
|
66b97be9d2 | ||
|
|
57909ebc61 | ||
|
|
d1090670a8 | ||
|
|
f4bcad1b06 | ||
|
|
6656708c8e | ||
|
|
bfe3fb2ed0 | ||
|
|
ec21521281 | ||
|
|
e71e671d7d | ||
|
|
df6b0fae21 | ||
|
|
69723a8bf4 | ||
|
|
76d907987a | ||
|
|
241caa6132 | ||
|
|
13b93f6d9d | ||
|
|
77555366f4 | ||
|
|
f3e8132bfc | ||
|
|
7510385cf4 | ||
|
|
e05b72615e | ||
|
|
b3f69d4088 | ||
|
|
8796c8fe06 | ||
|
|
b9a6a98fee | ||
|
|
acc9145d52 | ||
|
|
f9c8f53474 | ||
|
|
004e96517f | ||
|
|
957265b1c8 | ||
|
|
8807e282f4 | ||
|
|
c394974dc8 | ||
|
|
28386a4234 | ||
|
|
6f16c47d4f | ||
|
|
25062e37f4 | ||
|
|
2b1f8e4335 | ||
|
|
02690b6796 | ||
|
|
3897281015 | ||
|
|
8d0e5b93ed | ||
|
|
ef146032df | ||
|
|
1dc025fb36 | ||
|
|
30c0c84b93 | ||
|
|
4bd139f93b | ||
|
|
f59787add0 | ||
|
|
20c304a2db | ||
|
|
53526d9c80 | ||
|
|
68b4bc66ff | ||
|
|
805149daea | ||
|
|
b2529207e1 | ||
|
|
d2fe9b0590 | ||
|
|
eff4f82ad7 | ||
|
|
57327332c9 | ||
|
|
a2144ccb61 | ||
|
|
aa478fc510 | ||
|
|
659a0bc0fd | ||
|
|
f1ef28e544 | ||
|
|
fef680fb99 | ||
|
|
91a45a621a | ||
|
|
fe9512ca9c | ||
|
|
ff318599f5 | ||
|
|
d1ba90408d | ||
|
|
536f8d9cb9 | ||
|
|
6a9e871b08 | ||
|
|
d163d145d0 | ||
|
|
fdf0506976 | ||
|
|
c9d8fc3072 | ||
|
|
0bcf67a5f5 | ||
|
|
3e48753329 | ||
|
|
96441dbb33 | ||
|
|
6a0b63b185 | ||
|
|
9dea43fd34 | ||
|
|
465980dd8c | ||
|
|
03d04fd8d1 | ||
|
|
7d18c9b160 | ||
|
|
c097f98959 | ||
|
|
213d4ad928 | ||
|
|
710b3b00f5 | ||
|
|
d041d03fbf | ||
|
|
24b90e9888 | ||
|
|
4b83e798ac | ||
|
|
468f93f3df | ||
|
|
78d9dd5acb | ||
|
|
6ef7d4653d | ||
|
|
645eb637f2 | ||
|
|
268fdce5ac | ||
|
|
f9f3a05a43 | ||
|
|
8a92919b2e | ||
|
|
dbcd675300 | ||
|
|
4628af0e43 | ||
|
|
b1fedf5904 | ||
|
|
45ec03e615 | ||
|
|
570d36b695 | ||
|
|
b36697054e | ||
|
|
17149fe853 | ||
|
|
15c837f745 | ||
|
|
3f43ff05d0 | ||
|
|
d4dee21383 | ||
|
|
79da904767 | ||
|
|
0821797044 | ||
|
|
ad7ff62b56 | ||
|
|
f148d7d0d0 | ||
|
|
e19e3865e7 | ||
|
|
35f062d4e0 | ||
|
|
01328ba33c | ||
|
|
7caa138184 | ||
|
|
1b8c3f3081 | ||
|
|
3e4f36fb6f | ||
|
|
aedcb973f5 | ||
|
|
26dc720929 | ||
|
|
b5cc1c06df | ||
|
|
786c790307 | ||
|
|
3e8660bb61 | ||
|
|
997aed4ab3 | ||
|
|
f64ea058b9 | ||
|
|
96485ba252 | ||
|
|
a9bdcbcdd4 | ||
|
|
1d7f1cccba | ||
|
|
b002477c0d | ||
|
|
27f1447469 | ||
|
|
ff153cdd81 | ||
|
|
fe16329443 | ||
|
|
744e1cf2be | ||
|
|
ab2cf8c8c7 | ||
|
|
fbd001b797 | ||
|
|
4610be6f15 | ||
|
|
d5e34b649f | ||
|
|
7b49a94edd | ||
|
|
8dfcda6c5e | ||
|
|
756d97a9cb | ||
|
|
c0887dbeb9 | ||
|
|
b8f0ff217f | ||
|
|
cc805781e3 | ||
|
|
9531eca7a7 | ||
|
|
d7a1d5bbd2 | ||
|
|
c214168dcd | ||
|
|
dd085be5c7 | ||
|
|
bd7fbfff37 | ||
|
|
52a25fc720 | ||
|
|
384153d914 | ||
|
|
511ac5068b | ||
|
|
67e490ab53 | ||
|
|
b84cde1633 | ||
|
|
3350f7bd56 | ||
|
|
7510419836 | ||
|
|
7da3ef4e0c | ||
|
|
4c32171fbb | ||
|
|
470f178cde | ||
|
|
f9633505a2 | ||
|
|
de102d9898 | ||
|
|
9d503b12e6 | ||
|
|
4dc3bc1532 | ||
|
|
50da8cfbc6 | ||
|
|
bccfc127f3 | ||
|
|
2332d8756d | ||
|
|
a4abaed30a | ||
|
|
d47e18df1f | ||
|
|
c2d094da35 | ||
|
|
6e54b10239 | ||
|
|
e6c44ec52a | ||
|
|
39b8ecf785 | ||
|
|
d87f871334 | ||
|
|
07cea56e2b | ||
|
|
dbf3226f97 | ||
|
|
4b926edf24 | ||
|
|
ce0fd42995 | ||
|
|
bdf91443e0 | ||
|
|
68f4237e15 | ||
|
|
81fc747c03 | ||
|
|
3a25ed13b9 | ||
|
|
21c5eb6786 | ||
|
|
e85203e429 | ||
|
|
6b2d10d589 | ||
|
|
3d03de193e | ||
|
|
a56de72a6b | ||
|
|
0849bbbba6 | ||
|
|
0cd41d2036 | ||
|
|
a93bcd6ab6 | ||
|
|
77b72e160b | ||
|
|
b32c37f4af | ||
|
|
d0beea5cb3 | ||
|
|
30df6887c5 | ||
|
|
bc7823dda1 | ||
|
|
cbb195a313 | ||
|
|
097dc06c65 | ||
|
|
b06fbd25a0 | ||
|
|
89bbf274e5 | ||
|
|
d854177e5a | ||
|
|
aa9f82f2d4 | ||
|
|
2b45264628 | ||
|
|
4da299f431 | ||
|
|
9f9aa447a6 | ||
|
|
6a9f1597cb | ||
|
|
cddc48b851 | ||
|
|
84ab6d300c | ||
|
|
3c5026c2fb | ||
|
|
c3c8959d2e | ||
|
|
2c459d2636 | ||
|
|
a33c481dd5 | ||
|
|
d6b2f93e54 | ||
|
|
802e945829 | ||
|
|
a4a885f33a | ||
|
|
3380cebb28 | ||
|
|
21ed415f4f | ||
|
|
51dd89d36a | ||
|
|
bad96f231c | ||
|
|
184d72c444 | ||
|
|
6ca773050f | ||
|
|
648e8aaae0 | ||
|
|
ad9868b575 | ||
|
|
d4d10998f8 | ||
|
|
ba22c31deb | ||
|
|
f6be133a78 | ||
|
|
3768164f1f | ||
|
|
8465e7539f | ||
|
|
542eca5867 | ||
|
|
27a67c5f4a | ||
|
|
e00c40f2d5 | ||
|
|
b664e231dc | ||
|
|
92d6977f9e | ||
|
|
4059700468 | ||
|
|
196bdd83ba | ||
|
|
fbd52bc14e | ||
|
|
8013c988d0 | ||
|
|
460d6fcf12 | ||
|
|
92353c4853 | ||
|
|
8ca2a89f0f | ||
|
|
f54c2367f3 | ||
|
|
27452085e9 | ||
|
|
2bff7d9567 | ||
|
|
c3749f62fe | ||
|
|
b82c04a16a | ||
|
|
0ec099cdf5 | ||
|
|
d3f49094d8 | ||
|
|
4e2ad3bc62 | ||
|
|
05c287fcf7 | ||
|
|
c11cef4119 | ||
|
|
d6126cc5ce | ||
|
|
d88c925a68 | ||
|
|
372a572400 | ||
|
|
623ee8fbb1 | ||
|
|
729e0fc5ca | ||
|
|
d052cde6ca | ||
|
|
b52bbab903 | ||
|
|
9d42135ebf | ||
|
|
9ce5aa2189 | ||
|
|
e277292194 | ||
|
|
649961c831 | ||
|
|
e00cde2fbd | ||
|
|
25b89d191b | ||
|
|
0a60f77bfc | ||
|
|
66a80e439f | ||
|
|
d8cc25a54f | ||
|
|
39b9cfb348 | ||
|
|
c6087574be | ||
|
|
41c63cbfe9 | ||
|
|
f1afc81e7d | ||
|
|
018f8a19bb | ||
|
|
cccd007ba6 | ||
|
|
6d5b8baadf | ||
|
|
07e36415e4 | ||
|
|
8dc480826b | ||
|
|
533a5b87ec | ||
|
|
7bd83557c1 | ||
|
|
ef290e79b1 | ||
|
|
713b3f4f6d | ||
|
|
8fd9614f69 | ||
|
|
6682a98770 | ||
|
|
392b405978 | ||
|
|
be61850d18 | ||
|
|
f4208a2212 | ||
|
|
0b7278a2a8 | ||
|
|
bee078fe18 |
@@ -6,7 +6,7 @@ orbs:
|
||||
aws-cli: circleci/aws-cli@4.0
|
||||
eb: circleci/aws-elastic-beanstalk@2.0.1
|
||||
jobs:
|
||||
api-deploy:
|
||||
imex-api-deploy:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
steps:
|
||||
@@ -19,9 +19,9 @@ jobs:
|
||||
eb deploy
|
||||
eb status
|
||||
|
||||
hasura-migrate:
|
||||
imex-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
- image: cimg/node:18.18.2
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
@@ -38,12 +38,11 @@ jobs:
|
||||
hasura metadata apply --endpoint https://db.imex.online/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.imex.online/ --admin-secret << parameters.secret >>
|
||||
|
||||
app-build:
|
||||
imex-app-build:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
@@ -51,14 +50,19 @@ jobs:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build
|
||||
- run: npm run build:imex
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-production/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
app-beta-build:
|
||||
imex-app-beta-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
@@ -71,7 +75,7 @@ jobs:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build
|
||||
- run: npm run build:production:imex
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
@@ -79,13 +83,164 @@ jobs:
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
from: dist
|
||||
to: "s3://imex-online-beta/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
rome-api-deploy:
|
||||
docker:
|
||||
- image: "cimg/base:stable"
|
||||
steps:
|
||||
- checkout
|
||||
- eb/setup
|
||||
- run:
|
||||
command: |
|
||||
eb init romeonline-productionapi -r us-east-2 -p "Node.js 18 running on 64bit Amazon Linux 2"
|
||||
eb status --verbose
|
||||
eb deploy
|
||||
eb status
|
||||
|
||||
rome-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
default: $HASURA_ROME_PROD_SECRET
|
||||
working_directory: ~/repo/hasura
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Execute migration
|
||||
command: |
|
||||
npm install hasura-cli -g
|
||||
hasura migrate apply --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata apply --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
|
||||
rome-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:production:rome
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: dist
|
||||
to: "s3://rome-online-production/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
promanager-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:production:promanager
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: dist
|
||||
to: "s3://promanager-production/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
test-rome-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
default: $HASURA_ROME_TEST_SECRET
|
||||
working_directory: ~/repo/hasura
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Execute migration
|
||||
command: |
|
||||
npm install hasura-cli -g
|
||||
hasura migrate apply --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata apply --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.test.romeonline.io/ --admin-secret << parameters.secret >>
|
||||
|
||||
test-rome-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test:rome
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: dist
|
||||
to: "s3://rome-online-test/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
test-promanager-app-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test:promanager
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
aws_secret_access_key: AWS_SECRET_ACCESS_KEY
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: dist
|
||||
to: "s3://promanager-testing/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
test-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
- image: cimg/node:18.18.2
|
||||
parameters:
|
||||
secret:
|
||||
type: string
|
||||
@@ -98,14 +253,13 @@ jobs:
|
||||
name: Execute migration
|
||||
command: |
|
||||
npm install hasura-cli -g
|
||||
echo ${HASURA_TEST_SECRET}
|
||||
hasura migrate apply --endpoint https://db.test.bodyshop.app/ --admin-secret << parameters.secret >>
|
||||
hasura metadata apply --endpoint https://db.test.bodyshop.app/ --admin-secret << parameters.secret >>
|
||||
hasura metadata reload --endpoint https://db.test.bodyshop.app/ --admin-secret << parameters.secret >>
|
||||
|
||||
test-app-build:
|
||||
imex-test-app-build:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
working_directory: ~/repo/client
|
||||
|
||||
@@ -116,14 +270,14 @@ jobs:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test
|
||||
- run: npm run build:test:imex
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-test/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
test-app-beta-build:
|
||||
imex-test-app-beta-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
@@ -137,9 +291,7 @@ jobs:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test
|
||||
|
||||
- run: npm run sentry:sourcemaps
|
||||
- run: npm run build:test:imex
|
||||
|
||||
- aws-cli/setup:
|
||||
aws_access_key_id: AWS_ACCESS_KEY_ID
|
||||
@@ -147,10 +299,11 @@ jobs:
|
||||
region: AWS_REGION
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
from: dist
|
||||
to: "s3://imex-online-test-beta/"
|
||||
arguments: "--exclude '*.map'"
|
||||
|
||||
|
||||
admin-app-build:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
@@ -184,36 +337,66 @@ jobs:
|
||||
workflows:
|
||||
deploy_and_build:
|
||||
jobs:
|
||||
- api-deploy:
|
||||
- imex-api-deploy:
|
||||
filters:
|
||||
branches:
|
||||
only: master-AIO
|
||||
- imex-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- app-build:
|
||||
- imex-app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master-beta
|
||||
- hasura-migrate:
|
||||
only: master-AIO
|
||||
- imex-hasura-migrate:
|
||||
secret: ${HASURA_PROD_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- test-app-build:
|
||||
- rome-api-deploy:
|
||||
filters:
|
||||
branches:
|
||||
only: master-AIO
|
||||
- rome-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master-AIO
|
||||
- rome-hasura-migrate:
|
||||
secret: ${HASURA_PROD_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: master-AIO
|
||||
- imex-test-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test
|
||||
- test-app-beta-build:
|
||||
- imex-test-app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test-beta
|
||||
only: test-AIO
|
||||
- test-hasura-migrate:
|
||||
secret: ${HASURA_TEST_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: test
|
||||
only: test-AIO
|
||||
- test-rome-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test-AIO
|
||||
- test-promanager-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test-AIO
|
||||
- promanager-app-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master-AIO
|
||||
- test-rome-hasura-migrate:
|
||||
secret: ${HASURA_ROME_TEST_SECRET}
|
||||
filters:
|
||||
branches:
|
||||
only: test-AIO
|
||||
#- admin-app-build:
|
||||
#filters:
|
||||
#branches:
|
||||
|
||||
21
.editorconfig
Normal file
@@ -0,0 +1,21 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = false
|
||||
quote_type = single
|
||||
max_line_length = 100
|
||||
bracketSpacing = false
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
3
.gitignore
vendored
@@ -21,6 +21,7 @@ admin/coverage
|
||||
/build
|
||||
client/build
|
||||
admin/build
|
||||
client/dist
|
||||
# misc
|
||||
.DS_Store
|
||||
.env
|
||||
@@ -119,4 +120,4 @@ logs/oAuthClient-log.log
|
||||
|
||||
/*.env.*
|
||||
.idea/*
|
||||
.idea
|
||||
.idea
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
exports.default = {
|
||||
const config = {
|
||||
printWidth: 120,
|
||||
useTabs: false,
|
||||
tabWidth: 2,
|
||||
trailingComma: "es5",
|
||||
trailingComma: "none",
|
||||
semi: true,
|
||||
singleQuote: false,
|
||||
bracketSpacing: true,
|
||||
arrowParens: "always",
|
||||
jsxSingleQuote: false,
|
||||
bracketSameLine: false,
|
||||
endOfLine: "lf",
|
||||
importOrder: ["^@core/(.*)$", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"],
|
||||
importOrderSeparation: true,
|
||||
importOrderSortSpecifiers: true,
|
||||
endOfLine: "lf"
|
||||
// importOrder: ["^@core/(.*)$", "^@server/(.*)$", "^@ui/(.*)$", "^[./]"],
|
||||
// importOrderSeparation: true,
|
||||
// importOrderSortSpecifiers: true
|
||||
};
|
||||
|
||||
module.exports = config;
|
||||
|
||||
@@ -2,7 +2,7 @@ NGROK TEsting:
|
||||
./ngrok.exe http http://localhost:4000 -host-header="localhost:4000"
|
||||
|
||||
Finding deadfiles - run from client directory
|
||||
npx deadfile ./src/index.js --exclude build templates
|
||||
npx deadfile ./src/index.jsx --exclude build templates
|
||||
|
||||
#Crushing all hasura migrations by creating a new initialization from the server.
|
||||
hasura migrate create "Init" --from-server --endpoint https://db.imex.online/ --admin-secret 'Production-ImEXOnline!@#'
|
||||
@@ -11,4 +11,4 @@ Production-ImEXOnline!@#'
|
||||
hasura migrate status --endpoint https://db.imex.online/ --admin-secret 'Production-ImEXOnline!@#'
|
||||
|
||||
Generate the license file:
|
||||
$ generate-license-file --input package.json --output third-party-licenses.txt --overwrite
|
||||
$ generate-license-file --input package.json --output third-party-licenses.txt --overwrite
|
||||
|
||||
14
_reference/BodyshopFeatures.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"mobile": "date",
|
||||
"allAccess": "bool",
|
||||
"timetickets": "date",
|
||||
"payments": "date",
|
||||
"partsorders": "date",
|
||||
"bills": "Date",
|
||||
"export": "date",
|
||||
"csi": "Date",
|
||||
"courtesycars": "date",
|
||||
"media": "date",
|
||||
"visualboard": "date",
|
||||
"scoreboard": "date"
|
||||
}
|
||||
@@ -567,4 +567,4 @@
|
||||
"description": "Exempt"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
41
_reference/productionBoardNotes.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Production Board Notes:
|
||||
|
||||
## General Notes
|
||||
|
||||
- You can single click the lane footer to collapse/un-collapse the lane
|
||||
- You can double click the lane header to collapse/un-collapse the lane
|
||||
- If you need to scroll horizontally, you can hold shift and use the mouse scroll wheel, or press the mouse scroll wheel while scrolling
|
||||
|
||||
## Board Settings
|
||||
|
||||
#### Layout
|
||||
|
||||
- Board Orientation (Vertical or Horizontal)
|
||||
- This determines the orientation of the card layout on the board.
|
||||
- Horizontal is the default setting, and how the prior board was set up.
|
||||
- Vertical is the new setting and allows lanes to be displayed vertically, with a grid of cards
|
||||
- Card Size (Small, Medium, Large)
|
||||
- This determines the size of the cards on the board.
|
||||
- Small is the default setting, and how the prior board was set up.
|
||||
- Medium and Large are new settings and allow for larger cards to be displayed on the board.
|
||||
- Compact Cards (Tall or Wide)
|
||||
- Formally called 'Compact'
|
||||
- When on, data is displayed on the card vertically
|
||||
- when turned off, some fields may share horizontal space, tightening the card layout
|
||||
- Colored Cards (On or Off)
|
||||
- When on, cards are colored based on the Status color
|
||||
- Kiosk Mode (On or Off)
|
||||
- This should be turned on if the shop is using it on a tablet (Ipad)
|
||||
|
||||
#### Information
|
||||
|
||||
These allow users to turn fields on or off, turning them all off will show the card in the most minimal form
|
||||
|
||||
|
||||
### Statistics
|
||||
|
||||
- The statistics section allows users to see accumulations of both jobs on the board, and jobs in production.
|
||||
- you can click a statistic to turn it on and off, and drag and drop the statistics to rearrange them
|
||||
|
||||
### Filters
|
||||
- Allows you to set, and persist filters for estimators and insurance companies
|
||||
@@ -4,7 +4,7 @@ Clone Repository for:
|
||||
{
|
||||
"name": "node-webhook-scripts",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"main": "index.jsx",
|
||||
"dependencies": {
|
||||
"express": "^4.16.4"
|
||||
},
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: "IO Test API",
|
||||
cwd: "./io",
|
||||
script: "./server.js",
|
||||
env: {
|
||||
NODE_ENV: "test",
|
||||
},
|
||||
},
|
||||
apps: [
|
||||
{
|
||||
name: "IO Test API",
|
||||
cwd: "./io",
|
||||
script: "./server.js",
|
||||
env: {
|
||||
NODE_ENV: "test"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
name: "Bitbucket Webhook",
|
||||
script: "./webhook/index.js",
|
||||
env: {
|
||||
NODE_ENV: "production",
|
||||
},
|
||||
},
|
||||
],
|
||||
{
|
||||
name: "Bitbucket Webhook",
|
||||
script: "./webhook/index.jsx",
|
||||
env: {
|
||||
NODE_ENV: "production"
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
REACT_APP_GA_CODE=231099835
|
||||
REACT_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
REACT_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
REACT_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
14
client/.env.development.imex
Normal file
@@ -0,0 +1,14 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
VITE_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=IMEX
|
||||
14
client/.env.development.promanager
Normal file
@@ -0,0 +1,14 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc","authDomain":"imex-dev.firebaseapp.com","databaseURL":"https://imex-dev.firebaseio.com","projectId":"imex-dev","storageBucket":"imex-dev.appspot.com","messagingSenderId":"759548147434","appId":"1:759548147434:web:e8239868a48ceb36700993","measurementId":"G-K5XRBVVB4S"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
VITE_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BG3tzU7L2BXlGZ_3VLK4PNaRceoEXEnmHfxcVbRMF5o5g05ejslhVPki9kBM9cBBT-08Ad9kN3HSpS6JmrWD6h4'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=PROMANAGER
|
||||
15
client/.env.development.rome
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.dev.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/io-test
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/io-test
|
||||
VITE_APP_CLOUDINARY_API_KEY=957865933348715
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=http://localhost:4000
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_COUNTRY=USA
|
||||
VITE_APP_INSTANCE=ROME
|
||||
@@ -1,14 +0,0 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
|
||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.imex.online/v1/graphql
|
||||
REACT_APP_GA_CODE=231103507
|
||||
REACT_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"}
|
||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
REACT_APP_AXIOS_BASE_API_URL=https://api.imex.online/
|
||||
REACT_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
||||
REACT_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
15
client/.env.production.imex
Normal file
@@ -0,0 +1,15 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.imex.online/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.imex.online/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={"apiKey":"AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU","authDomain":"imex-prod.firebaseapp.com","databaseURL":"https://imex-prod.firebaseio.com","projectId":"imex-prod","storageBucket":"imex-prod.appspot.com","messagingSenderId":"253497221485","appId":"1:253497221485:web:3c81c483b94db84b227a64","measurementId":"G-NTWBKG2L0M"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.imex.online/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.imex.online
|
||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
VITE_APP_INSTANCE=IMEX
|
||||
15
client/.env.production.promanager
Normal file
@@ -0,0 +1,15 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BMgZT1NZztW2DsJl8Mg2L04hgY9FzAg6b8fbzgNAfww2VDzH3VE63Ot9EaP_U7KWS2JT-7HPHaw0T_Tw_5vkZc8'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
VITE_APP_INSTANCE=PROMANAGER
|
||||
15
client/.env.production.rome
Normal file
@@ -0,0 +1,15 @@
|
||||
GENERATE_SOURCEMAP=true
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.romeonline.io
|
||||
VITE_APP_SPLIT_API=et9pjkik6bn67he5evpmpr1agoo7gactphgk
|
||||
VITE_APP_INSTANCE=ROME
|
||||
@@ -1,14 +0,0 @@
|
||||
REACT_APP_GRAPHQL_ENDPOINT=https://db.test.bodyshop.app/v1/graphql
|
||||
REACT_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.bodyshop.app/v1/graphql
|
||||
REACT_APP_GA_CODE=231099835
|
||||
REACT_APP_FIREBASE_CONFIG={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||
REACT_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
REACT_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
REACT_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
REACT_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
REACT_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||
REACT_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
REACT_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/
|
||||
REACT_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
REACT_APP_IS_TEST=true
|
||||
REACT_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
15
client/.env.test.imex
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.test.bodyshop.app/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.bodyshop.app/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey":"AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c", "authDomain":"imex-test.firebaseapp.com", "projectId":"imex-test", "storageBucket":"imex-test.appspot.com", "messagingSenderId":"991923618608", "appId":"1:991923618608:web:633437569cdad78299bef5", "measurementId":"G-TW0XLZEH18"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.test.imex.online/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports3.test.imex.online
|
||||
VITE_APP_IS_TEST=true
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=IMEX
|
||||
15
client/.env.test.promanager
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231099835
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BN2GcDPjipR5MTEosO5dT4CfQ3cmrdBIsI4juoOQrRijn_5aRiHlwj1mlq0W145mOusx6xynEKl_tvYJhpCc9lo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.test.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
|
||||
VITE_APP_IS_TEST=true
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=PROMANAGER
|
||||
15
client/.env.test.rome
Normal file
@@ -0,0 +1,15 @@
|
||||
VITE_APP_GRAPHQL_ENDPOINT=https://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GRAPHQL_ENDPOINT_WS=wss://db.test.romeonline.io/v1/graphql
|
||||
VITE_APP_GA_CODE=231103507
|
||||
VITE_APP_FIREBASE_CONFIG={ "apiKey": "AIzaSyAuLQR9SV5LsVxjU8wh9hvFLdhcAHU6cxE", "authDomain": "rome-prod-1.firebaseapp.com", "projectId": "rome-prod-1", "storageBucket": "rome-prod-1.appspot.com", "messagingSenderId": "147786367145", "appId": "1:147786367145:web:9d4cba68071c3f29a8a9b8", "measurementId": "G-G8Z9DRHTZS"}
|
||||
VITE_APP_CLOUDINARY_ENDPOINT_API=https://api.cloudinary.com/v1_1/bodyshop
|
||||
VITE_APP_CLOUDINARY_ENDPOINT=https://res.cloudinary.com/bodyshop
|
||||
VITE_APP_CLOUDINARY_API_KEY=473322739956866
|
||||
VITE_APP_CLOUDINARY_THUMB_TRANSFORMATIONS=c_fill,h_250,w_250
|
||||
VITE_APP_FIREBASE_PUBLIC_VAPID_KEY='BP1B7ZTYpn-KMt6nOxlld6aS8Skt3Q7ZLEqP0hAvGHxG4UojPYiXZ6kPlzZkUC5jH-EcWXomTLtmadAIxurfcHo'
|
||||
VITE_APP_STRIPE_PUBLIC_KEY=pk_test_51GqB4TJl3nQjrZ0wCQWAxAhlNF8jKe0tipIa6ExBaxwJGitwvFsIZUEua4dUzaMIAuXp4qwYHXx7lgjyQSwP0Pe900vzm38C7g
|
||||
VITE_APP_AXIOS_BASE_API_URL=https://api.test.romeonline.io/
|
||||
VITE_APP_REPORTS_SERVER_URL=https://reports.test.romeonline.io
|
||||
VITE_APP_IS_TEST=true
|
||||
VITE_APP_SPLIT_API=ts615lqgnmk84thn72uk18uu5pgce6e0l4rc
|
||||
VITE_APP_INSTANCE=ROME
|
||||
8
client/.eslintrc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": [
|
||||
"react-app"
|
||||
],
|
||||
"rules": {
|
||||
"no-useless-rename": "off"
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
// craco.config.js
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const CracoLessPlugin = require("craco-less");
|
||||
const {convertLegacyToken} = require('@ant-design/compatible/lib');
|
||||
const {theme} = require('antd/lib');
|
||||
|
||||
const {defaultAlgorithm, defaultSeed} = theme;
|
||||
|
||||
const mapToken = defaultAlgorithm(defaultSeed);
|
||||
const v4Token = convertLegacyToken(mapToken);
|
||||
|
||||
// TODO, At the moment we are using less in the Dashboard. Once we remove this we can remove the less processor entirely.
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
// {
|
||||
// plugin: SentryWebpackPlugin,
|
||||
// options: {
|
||||
// // sentry-cli configuration
|
||||
// authToken:
|
||||
// "6b45b028a02342db97a9a2f92c0959058665443d379d4a3a876430009e744260",
|
||||
// org: "snapt-software",
|
||||
// project: "imexonline",
|
||||
// release: process.env.REACT_APP_GIT_SHA,
|
||||
//
|
||||
// // webpack-specific configuration
|
||||
// include: ".",
|
||||
// ignore: ["node_modules", "webpack.config.js"],
|
||||
// },
|
||||
// },
|
||||
{
|
||||
plugin: CracoLessPlugin,
|
||||
options: {
|
||||
lessLoaderOptions: {
|
||||
lessOptions: {
|
||||
modifyVars: {...v4Token},
|
||||
javascriptEnabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
webpack: {
|
||||
configure: (webpackConfig) => {
|
||||
return {
|
||||
...webpackConfig,
|
||||
// Required for Dev Server
|
||||
devServer: {
|
||||
...webpackConfig.devServer,
|
||||
allowedHosts: 'all',
|
||||
},
|
||||
optimization: {
|
||||
...webpackConfig.optimization,
|
||||
// Workaround for CircleCI bug caused by the number of CPUs shown
|
||||
// https://github.com/facebook/create-react-app/issues/8320
|
||||
minimizer: webpackConfig.optimization.minimizer.map((item) => {
|
||||
if (item instanceof TerserPlugin) {
|
||||
item.options.parallel = 2;
|
||||
}
|
||||
|
||||
return item;
|
||||
}),
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
devtool: "source-map",
|
||||
};
|
||||
@@ -1,17 +1,17 @@
|
||||
const {defineConfig} = require('cypress')
|
||||
const { defineConfig } = require("cypress");
|
||||
|
||||
module.exports = defineConfig({
|
||||
experimentalStudio: true,
|
||||
env: {
|
||||
FIREBASE_USERNAME: 'cypress@imex.test',
|
||||
FIREBASE_PASSWORD: 'cypress',
|
||||
experimentalStudio: true,
|
||||
env: {
|
||||
FIREBASE_USERNAME: "cypress@imex.test",
|
||||
FIREBASE_PASSWORD: "cypress"
|
||||
},
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require("./cypress/plugins/index.js")(on, config);
|
||||
},
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
})
|
||||
baseUrl: "http://localhost:3000"
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,24 +1,19 @@
|
||||
/// <reference types="Cypress" />
|
||||
const {FIREBASE_USERNAME, FIREBASE_PASSWORcD} = Cypress.env();
|
||||
const { FIREBASE_USERNAME, FIREBASE_PASSWORcD } = Cypress.env();
|
||||
describe("Renders the General Page", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
});
|
||||
it("Renders Correctly", () => {
|
||||
});
|
||||
it("Has the Slogan", () => {
|
||||
cy.findByText("A whole x22new kind of shop management system.").should(
|
||||
"exist"
|
||||
);
|
||||
/* ==== Generated with Cypress Studio ==== */
|
||||
cy.get(
|
||||
".ant-menu-item-active > .ant-menu-title-content > .header0-item-block"
|
||||
).click();
|
||||
cy.get("#email").clear();
|
||||
cy.get("#email").type("patrick@imex.dev");
|
||||
cy.get("#password").clear();
|
||||
cy.get("#password").type("patrick123{enter}");
|
||||
cy.get(".ant-form > .ant-btn").click();
|
||||
/* ==== End Cypress Studio ==== */
|
||||
});
|
||||
beforeEach(() => {
|
||||
cy.visit("/");
|
||||
});
|
||||
it("Renders Correctly", () => {});
|
||||
it("Has the Slogan", () => {
|
||||
cy.findByText("A whole x22new kind of shop management system.").should("exist");
|
||||
/* ==== Generated with Cypress Studio ==== */
|
||||
cy.get(".ant-menu-item-active > .ant-menu-title-content > .header0-item-block").click();
|
||||
cy.get("#email").clear();
|
||||
cy.get("#email").type("patrick@imex.dev");
|
||||
cy.get("#password").clear();
|
||||
cy.get("#password").type("patrick123{enter}");
|
||||
cy.get(".ant-form > .ant-btn").click();
|
||||
/* ==== End Cypress Studio ==== */
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,133 +11,114 @@
|
||||
// please read our getting started guide:
|
||||
// https://on.cypress.io/introduction-to-cypress
|
||||
|
||||
describe('example to-do app', () => {
|
||||
describe("example to-do app", () => {
|
||||
beforeEach(() => {
|
||||
// Cypress starts out with a blank slate for each test
|
||||
// so we must tell it to visit our website with the `cy.visit()` command.
|
||||
// Since we want to visit the same URL at the start of all our tests,
|
||||
// we include it in our beforeEach function so that it runs before each test
|
||||
cy.visit("https://example.cypress.io/todo");
|
||||
});
|
||||
|
||||
it("displays two todo items by default", () => {
|
||||
// We use the `cy.get()` command to get all elements that match the selector.
|
||||
// Then, we use `should` to assert that there are two matched items,
|
||||
// which are the two default items.
|
||||
cy.get(".todo-list li").should("have.length", 2);
|
||||
|
||||
// We can go even further and check that the default todos each contain
|
||||
// the correct text. We use the `first` and `last` functions
|
||||
// to get just the first and last matched elements individually,
|
||||
// and then perform an assertion with `should`.
|
||||
cy.get(".todo-list li").first().should("have.text", "Pay electric bill");
|
||||
cy.get(".todo-list li").last().should("have.text", "Walk the dog");
|
||||
});
|
||||
|
||||
it("can add new todo items", () => {
|
||||
// We'll store our item text in a variable so we can reuse it
|
||||
const newItem = "Feed the cat";
|
||||
|
||||
// Let's get the input element and use the `type` command to
|
||||
// input our new list item. After typing the content of our item,
|
||||
// we need to type the enter key as well in order to submit the input.
|
||||
// This input has a data-test attribute so we'll use that to select the
|
||||
// element in accordance with best practices:
|
||||
// https://on.cypress.io/selecting-elements
|
||||
cy.get("[data-test=new-todo]").type(`${newItem}{enter}`);
|
||||
|
||||
// Now that we've typed our new item, let's check that it actually was added to the list.
|
||||
// Since it's the newest item, it should exist as the last element in the list.
|
||||
// In addition, with the two default items, we should have a total of 3 elements in the list.
|
||||
// Since assertions yield the element that was asserted on,
|
||||
// we can chain both of these assertions together into a single statement.
|
||||
cy.get(".todo-list li").should("have.length", 3).last().should("have.text", newItem);
|
||||
});
|
||||
|
||||
it("can check off an item as completed", () => {
|
||||
// In addition to using the `get` command to get an element by selector,
|
||||
// we can also use the `contains` command to get an element by its contents.
|
||||
// However, this will yield the <label>, which is lowest-level element that contains the text.
|
||||
// In order to check the item, we'll find the <input> element for this <label>
|
||||
// by traversing up the dom to the parent element. From there, we can `find`
|
||||
// the child checkbox <input> element and use the `check` command to check it.
|
||||
cy.contains("Pay electric bill").parent().find("input[type=checkbox]").check();
|
||||
|
||||
// Now that we've checked the button, we can go ahead and make sure
|
||||
// that the list element is now marked as completed.
|
||||
// Again we'll use `contains` to find the <label> element and then use the `parents` command
|
||||
// to traverse multiple levels up the dom until we find the corresponding <li> element.
|
||||
// Once we get that element, we can assert that it has the completed class.
|
||||
cy.contains("Pay electric bill").parents("li").should("have.class", "completed");
|
||||
});
|
||||
|
||||
context("with a checked task", () => {
|
||||
beforeEach(() => {
|
||||
// Cypress starts out with a blank slate for each test
|
||||
// so we must tell it to visit our website with the `cy.visit()` command.
|
||||
// Since we want to visit the same URL at the start of all our tests,
|
||||
// we include it in our beforeEach function so that it runs before each test
|
||||
cy.visit('https://example.cypress.io/todo')
|
||||
})
|
||||
// We'll take the command we used above to check off an element
|
||||
// Since we want to perform multiple tests that start with checking
|
||||
// one element, we put it in the beforeEach hook
|
||||
// so that it runs at the start of every test.
|
||||
cy.contains("Pay electric bill").parent().find("input[type=checkbox]").check();
|
||||
});
|
||||
|
||||
it('displays two todo items by default', () => {
|
||||
// We use the `cy.get()` command to get all elements that match the selector.
|
||||
// Then, we use `should` to assert that there are two matched items,
|
||||
// which are the two default items.
|
||||
cy.get('.todo-list li').should('have.length', 2)
|
||||
it("can filter for uncompleted tasks", () => {
|
||||
// We'll click on the "active" button in order to
|
||||
// display only incomplete items
|
||||
cy.contains("Active").click();
|
||||
|
||||
// We can go even further and check that the default todos each contain
|
||||
// the correct text. We use the `first` and `last` functions
|
||||
// to get just the first and last matched elements individually,
|
||||
// and then perform an assertion with `should`.
|
||||
cy.get('.todo-list li').first().should('have.text', 'Pay electric bill')
|
||||
cy.get('.todo-list li').last().should('have.text', 'Walk the dog')
|
||||
})
|
||||
// After filtering, we can assert that there is only the one
|
||||
// incomplete item in the list.
|
||||
cy.get(".todo-list li").should("have.length", 1).first().should("have.text", "Walk the dog");
|
||||
|
||||
it('can add new todo items', () => {
|
||||
// We'll store our item text in a variable so we can reuse it
|
||||
const newItem = 'Feed the cat'
|
||||
// For good measure, let's also assert that the task we checked off
|
||||
// does not exist on the page.
|
||||
cy.contains("Pay electric bill").should("not.exist");
|
||||
});
|
||||
|
||||
// Let's get the input element and use the `type` command to
|
||||
// input our new list item. After typing the content of our item,
|
||||
// we need to type the enter key as well in order to submit the input.
|
||||
// This input has a data-test attribute so we'll use that to select the
|
||||
// element in accordance with best practices:
|
||||
// https://on.cypress.io/selecting-elements
|
||||
cy.get('[data-test=new-todo]').type(`${newItem}{enter}`)
|
||||
it("can filter for completed tasks", () => {
|
||||
// We can perform similar steps as the test above to ensure
|
||||
// that only completed tasks are shown
|
||||
cy.contains("Completed").click();
|
||||
|
||||
// Now that we've typed our new item, let's check that it actually was added to the list.
|
||||
// Since it's the newest item, it should exist as the last element in the list.
|
||||
// In addition, with the two default items, we should have a total of 3 elements in the list.
|
||||
// Since assertions yield the element that was asserted on,
|
||||
// we can chain both of these assertions together into a single statement.
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 3)
|
||||
.last()
|
||||
.should('have.text', newItem)
|
||||
})
|
||||
cy.get(".todo-list li").should("have.length", 1).first().should("have.text", "Pay electric bill");
|
||||
|
||||
it('can check off an item as completed', () => {
|
||||
// In addition to using the `get` command to get an element by selector,
|
||||
// we can also use the `contains` command to get an element by its contents.
|
||||
// However, this will yield the <label>, which is lowest-level element that contains the text.
|
||||
// In order to check the item, we'll find the <input> element for this <label>
|
||||
// by traversing up the dom to the parent element. From there, we can `find`
|
||||
// the child checkbox <input> element and use the `check` command to check it.
|
||||
cy.contains('Pay electric bill')
|
||||
.parent()
|
||||
.find('input[type=checkbox]')
|
||||
.check()
|
||||
cy.contains("Walk the dog").should("not.exist");
|
||||
});
|
||||
|
||||
// Now that we've checked the button, we can go ahead and make sure
|
||||
// that the list element is now marked as completed.
|
||||
// Again we'll use `contains` to find the <label> element and then use the `parents` command
|
||||
// to traverse multiple levels up the dom until we find the corresponding <li> element.
|
||||
// Once we get that element, we can assert that it has the completed class.
|
||||
cy.contains('Pay electric bill')
|
||||
.parents('li')
|
||||
.should('have.class', 'completed')
|
||||
})
|
||||
it("can delete all completed tasks", () => {
|
||||
// First, let's click the "Clear completed" button
|
||||
// `contains` is actually serving two purposes here.
|
||||
// First, it's ensuring that the button exists within the dom.
|
||||
// This button only appears when at least one task is checked
|
||||
// so this command is implicitly verifying that it does exist.
|
||||
// Second, it selects the button so we can click it.
|
||||
cy.contains("Clear completed").click();
|
||||
|
||||
context('with a checked task', () => {
|
||||
beforeEach(() => {
|
||||
// We'll take the command we used above to check off an element
|
||||
// Since we want to perform multiple tests that start with checking
|
||||
// one element, we put it in the beforeEach hook
|
||||
// so that it runs at the start of every test.
|
||||
cy.contains('Pay electric bill')
|
||||
.parent()
|
||||
.find('input[type=checkbox]')
|
||||
.check()
|
||||
})
|
||||
// Then we can make sure that there is only one element
|
||||
// in the list and our element does not exist
|
||||
cy.get(".todo-list li").should("have.length", 1).should("not.have.text", "Pay electric bill");
|
||||
|
||||
it('can filter for uncompleted tasks', () => {
|
||||
// We'll click on the "active" button in order to
|
||||
// display only incomplete items
|
||||
cy.contains('Active').click()
|
||||
|
||||
// After filtering, we can assert that there is only the one
|
||||
// incomplete item in the list.
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.first()
|
||||
.should('have.text', 'Walk the dog')
|
||||
|
||||
// For good measure, let's also assert that the task we checked off
|
||||
// does not exist on the page.
|
||||
cy.contains('Pay electric bill').should('not.exist')
|
||||
})
|
||||
|
||||
it('can filter for completed tasks', () => {
|
||||
// We can perform similar steps as the test above to ensure
|
||||
// that only completed tasks are shown
|
||||
cy.contains('Completed').click()
|
||||
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.first()
|
||||
.should('have.text', 'Pay electric bill')
|
||||
|
||||
cy.contains('Walk the dog').should('not.exist')
|
||||
})
|
||||
|
||||
it('can delete all completed tasks', () => {
|
||||
// First, let's click the "Clear completed" button
|
||||
// `contains` is actually serving two purposes here.
|
||||
// First, it's ensuring that the button exists within the dom.
|
||||
// This button only appears when at least one task is checked
|
||||
// so this command is implicitly verifying that it does exist.
|
||||
// Second, it selects the button so we can click it.
|
||||
cy.contains('Clear completed').click()
|
||||
|
||||
// Then we can make sure that there is only one element
|
||||
// in the list and our element does not exist
|
||||
cy.get('.todo-list li')
|
||||
.should('have.length', 1)
|
||||
.should('not.have.text', 'Pay electric bill')
|
||||
|
||||
// Finally, make sure that the clear button no longer exists.
|
||||
cy.contains('Clear completed').should('not.exist')
|
||||
})
|
||||
})
|
||||
})
|
||||
// Finally, make sure that the clear button no longer exists.
|
||||
cy.contains("Clear completed").should("not.exist");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,299 +1,284 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Actions', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/actions')
|
||||
})
|
||||
context("Actions", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/actions");
|
||||
});
|
||||
|
||||
// https://on.cypress.io/interacting-with-elements
|
||||
// https://on.cypress.io/interacting-with-elements
|
||||
|
||||
it('.type() - type into a DOM element', () => {
|
||||
// https://on.cypress.io/type
|
||||
cy.get('.action-email')
|
||||
.type('fake@email.com').should('have.value', 'fake@email.com')
|
||||
it(".type() - type into a DOM element", () => {
|
||||
// https://on.cypress.io/type
|
||||
cy.get(".action-email")
|
||||
.type("fake@email.com")
|
||||
.should("have.value", "fake@email.com")
|
||||
|
||||
// .type() with special character sequences
|
||||
.type('{leftarrow}{rightarrow}{uparrow}{downarrow}')
|
||||
.type('{del}{selectall}{backspace}')
|
||||
// .type() with special character sequences
|
||||
.type("{leftarrow}{rightarrow}{uparrow}{downarrow}")
|
||||
.type("{del}{selectall}{backspace}")
|
||||
|
||||
// .type() with key modifiers
|
||||
.type('{alt}{option}') //these are equivalent
|
||||
.type('{ctrl}{control}') //these are equivalent
|
||||
.type('{meta}{command}{cmd}') //these are equivalent
|
||||
.type('{shift}')
|
||||
// .type() with key modifiers
|
||||
.type("{alt}{option}") //these are equivalent
|
||||
.type("{ctrl}{control}") //these are equivalent
|
||||
.type("{meta}{command}{cmd}") //these are equivalent
|
||||
.type("{shift}")
|
||||
|
||||
// Delay each keypress by 0.1 sec
|
||||
.type('slow.typing@email.com', {delay: 100})
|
||||
.should('have.value', 'slow.typing@email.com')
|
||||
// Delay each keypress by 0.1 sec
|
||||
.type("slow.typing@email.com", { delay: 100 })
|
||||
.should("have.value", "slow.typing@email.com");
|
||||
|
||||
cy.get('.action-disabled')
|
||||
// Ignore error checking prior to type
|
||||
// like whether the input is visible or disabled
|
||||
.type('disabled error checking', {force: true})
|
||||
.should('have.value', 'disabled error checking')
|
||||
})
|
||||
cy.get(".action-disabled")
|
||||
// Ignore error checking prior to type
|
||||
// like whether the input is visible or disabled
|
||||
.type("disabled error checking", { force: true })
|
||||
.should("have.value", "disabled error checking");
|
||||
});
|
||||
|
||||
it('.focus() - focus on a DOM element', () => {
|
||||
// https://on.cypress.io/focus
|
||||
cy.get('.action-focus').focus()
|
||||
.should('have.class', 'focus')
|
||||
.prev().should('have.attr', 'style', 'color: orange;')
|
||||
})
|
||||
it(".focus() - focus on a DOM element", () => {
|
||||
// https://on.cypress.io/focus
|
||||
cy.get(".action-focus").focus().should("have.class", "focus").prev().should("have.attr", "style", "color: orange;");
|
||||
});
|
||||
|
||||
it('.blur() - blur off a DOM element', () => {
|
||||
// https://on.cypress.io/blur
|
||||
cy.get('.action-blur').type('About to blur').blur()
|
||||
.should('have.class', 'error')
|
||||
.prev().should('have.attr', 'style', 'color: red;')
|
||||
})
|
||||
it(".blur() - blur off a DOM element", () => {
|
||||
// https://on.cypress.io/blur
|
||||
cy.get(".action-blur")
|
||||
.type("About to blur")
|
||||
.blur()
|
||||
.should("have.class", "error")
|
||||
.prev()
|
||||
.should("have.attr", "style", "color: red;");
|
||||
});
|
||||
|
||||
it('.clear() - clears an input or textarea element', () => {
|
||||
// https://on.cypress.io/clear
|
||||
cy.get('.action-clear').type('Clear this text')
|
||||
.should('have.value', 'Clear this text')
|
||||
.clear()
|
||||
.should('have.value', '')
|
||||
})
|
||||
it(".clear() - clears an input or textarea element", () => {
|
||||
// https://on.cypress.io/clear
|
||||
cy.get(".action-clear")
|
||||
.type("Clear this text")
|
||||
.should("have.value", "Clear this text")
|
||||
.clear()
|
||||
.should("have.value", "");
|
||||
});
|
||||
|
||||
it('.submit() - submit a form', () => {
|
||||
// https://on.cypress.io/submit
|
||||
cy.get('.action-form')
|
||||
.find('[type="text"]').type('HALFOFF')
|
||||
it(".submit() - submit a form", () => {
|
||||
// https://on.cypress.io/submit
|
||||
cy.get(".action-form").find('[type="text"]').type("HALFOFF");
|
||||
|
||||
cy.get('.action-form').submit()
|
||||
.next().should('contain', 'Your form has been submitted!')
|
||||
})
|
||||
cy.get(".action-form").submit().next().should("contain", "Your form has been submitted!");
|
||||
});
|
||||
|
||||
it('.click() - click on a DOM element', () => {
|
||||
// https://on.cypress.io/click
|
||||
cy.get('.action-btn').click()
|
||||
it(".click() - click on a DOM element", () => {
|
||||
// https://on.cypress.io/click
|
||||
cy.get(".action-btn").click();
|
||||
|
||||
// You can click on 9 specific positions of an element:
|
||||
// -----------------------------------
|
||||
// | topLeft top topRight |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | left center right |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | bottomLeft bottom bottomRight |
|
||||
// -----------------------------------
|
||||
// You can click on 9 specific positions of an element:
|
||||
// -----------------------------------
|
||||
// | topLeft top topRight |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | left center right |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | bottomLeft bottom bottomRight |
|
||||
// -----------------------------------
|
||||
|
||||
// clicking in the center of the element is the default
|
||||
cy.get('#action-canvas').click()
|
||||
// clicking in the center of the element is the default
|
||||
cy.get("#action-canvas").click();
|
||||
|
||||
cy.get('#action-canvas').click('topLeft')
|
||||
cy.get('#action-canvas').click('top')
|
||||
cy.get('#action-canvas').click('topRight')
|
||||
cy.get('#action-canvas').click('left')
|
||||
cy.get('#action-canvas').click('right')
|
||||
cy.get('#action-canvas').click('bottomLeft')
|
||||
cy.get('#action-canvas').click('bottom')
|
||||
cy.get('#action-canvas').click('bottomRight')
|
||||
cy.get("#action-canvas").click("topLeft");
|
||||
cy.get("#action-canvas").click("top");
|
||||
cy.get("#action-canvas").click("topRight");
|
||||
cy.get("#action-canvas").click("left");
|
||||
cy.get("#action-canvas").click("right");
|
||||
cy.get("#action-canvas").click("bottomLeft");
|
||||
cy.get("#action-canvas").click("bottom");
|
||||
cy.get("#action-canvas").click("bottomRight");
|
||||
|
||||
// .click() accepts an x and y coordinate
|
||||
// that controls where the click occurs :)
|
||||
// .click() accepts an x and y coordinate
|
||||
// that controls where the click occurs :)
|
||||
|
||||
cy.get('#action-canvas')
|
||||
.click(80, 75) // click 80px on x coord and 75px on y coord
|
||||
.click(170, 75)
|
||||
.click(80, 165)
|
||||
.click(100, 185)
|
||||
.click(125, 190)
|
||||
.click(150, 185)
|
||||
.click(170, 165)
|
||||
cy.get("#action-canvas")
|
||||
.click(80, 75) // click 80px on x coord and 75px on y coord
|
||||
.click(170, 75)
|
||||
.click(80, 165)
|
||||
.click(100, 185)
|
||||
.click(125, 190)
|
||||
.click(150, 185)
|
||||
.click(170, 165);
|
||||
|
||||
// click multiple elements by passing multiple: true
|
||||
cy.get('.action-labels>.label').click({multiple: true})
|
||||
// click multiple elements by passing multiple: true
|
||||
cy.get(".action-labels>.label").click({ multiple: true });
|
||||
|
||||
// Ignore error checking prior to clicking
|
||||
cy.get('.action-opacity>.btn').click({force: true})
|
||||
})
|
||||
// Ignore error checking prior to clicking
|
||||
cy.get(".action-opacity>.btn").click({ force: true });
|
||||
});
|
||||
|
||||
it('.dblclick() - double click on a DOM element', () => {
|
||||
// https://on.cypress.io/dblclick
|
||||
it(".dblclick() - double click on a DOM element", () => {
|
||||
// https://on.cypress.io/dblclick
|
||||
|
||||
// Our app has a listener on 'dblclick' event in our 'scripts.js'
|
||||
// that hides the div and shows an input on double click
|
||||
cy.get('.action-div').dblclick().should('not.be.visible')
|
||||
cy.get('.action-input-hidden').should('be.visible')
|
||||
})
|
||||
// Our app has a listener on 'dblclick' event in our 'scripts.js'
|
||||
// that hides the div and shows an input on double click
|
||||
cy.get(".action-div").dblclick().should("not.be.visible");
|
||||
cy.get(".action-input-hidden").should("be.visible");
|
||||
});
|
||||
|
||||
it('.rightclick() - right click on a DOM element', () => {
|
||||
// https://on.cypress.io/rightclick
|
||||
it(".rightclick() - right click on a DOM element", () => {
|
||||
// https://on.cypress.io/rightclick
|
||||
|
||||
// Our app has a listener on 'contextmenu' event in our 'scripts.js'
|
||||
// that hides the div and shows an input on right click
|
||||
cy.get('.rightclick-action-div').rightclick().should('not.be.visible')
|
||||
cy.get('.rightclick-action-input-hidden').should('be.visible')
|
||||
})
|
||||
// Our app has a listener on 'contextmenu' event in our 'scripts.js'
|
||||
// that hides the div and shows an input on right click
|
||||
cy.get(".rightclick-action-div").rightclick().should("not.be.visible");
|
||||
cy.get(".rightclick-action-input-hidden").should("be.visible");
|
||||
});
|
||||
|
||||
it('.check() - check a checkbox or radio element', () => {
|
||||
// https://on.cypress.io/check
|
||||
it(".check() - check a checkbox or radio element", () => {
|
||||
// https://on.cypress.io/check
|
||||
|
||||
// By default, .check() will check all
|
||||
// matching checkbox or radio elements in succession, one after another
|
||||
cy.get('.action-checkboxes [type="checkbox"]').not('[disabled]')
|
||||
.check().should('be.checked')
|
||||
// By default, .check() will check all
|
||||
// matching checkbox or radio elements in succession, one after another
|
||||
cy.get('.action-checkboxes [type="checkbox"]').not("[disabled]").check().should("be.checked");
|
||||
|
||||
cy.get('.action-radios [type="radio"]').not('[disabled]')
|
||||
.check().should('be.checked')
|
||||
cy.get('.action-radios [type="radio"]').not("[disabled]").check().should("be.checked");
|
||||
|
||||
// .check() accepts a value argument
|
||||
cy.get('.action-radios [type="radio"]')
|
||||
.check('radio1').should('be.checked')
|
||||
// .check() accepts a value argument
|
||||
cy.get('.action-radios [type="radio"]').check("radio1").should("be.checked");
|
||||
|
||||
// .check() accepts an array of values
|
||||
cy.get('.action-multiple-checkboxes [type="checkbox"]')
|
||||
.check(['checkbox1', 'checkbox2']).should('be.checked')
|
||||
// .check() accepts an array of values
|
||||
cy.get('.action-multiple-checkboxes [type="checkbox"]').check(["checkbox1", "checkbox2"]).should("be.checked");
|
||||
|
||||
// Ignore error checking prior to checking
|
||||
cy.get('.action-checkboxes [disabled]')
|
||||
.check({force: true}).should('be.checked')
|
||||
// Ignore error checking prior to checking
|
||||
cy.get(".action-checkboxes [disabled]").check({ force: true }).should("be.checked");
|
||||
|
||||
cy.get('.action-radios [type="radio"]')
|
||||
.check('radio3', {force: true}).should('be.checked')
|
||||
})
|
||||
cy.get('.action-radios [type="radio"]').check("radio3", { force: true }).should("be.checked");
|
||||
});
|
||||
|
||||
it('.uncheck() - uncheck a checkbox element', () => {
|
||||
// https://on.cypress.io/uncheck
|
||||
it(".uncheck() - uncheck a checkbox element", () => {
|
||||
// https://on.cypress.io/uncheck
|
||||
|
||||
// By default, .uncheck() will uncheck all matching
|
||||
// checkbox elements in succession, one after another
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.not('[disabled]')
|
||||
.uncheck().should('not.be.checked')
|
||||
// By default, .uncheck() will uncheck all matching
|
||||
// checkbox elements in succession, one after another
|
||||
cy.get('.action-check [type="checkbox"]').not("[disabled]").uncheck().should("not.be.checked");
|
||||
|
||||
// .uncheck() accepts a value argument
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.check('checkbox1')
|
||||
.uncheck('checkbox1').should('not.be.checked')
|
||||
// .uncheck() accepts a value argument
|
||||
cy.get('.action-check [type="checkbox"]').check("checkbox1").uncheck("checkbox1").should("not.be.checked");
|
||||
|
||||
// .uncheck() accepts an array of values
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.check(['checkbox1', 'checkbox3'])
|
||||
.uncheck(['checkbox1', 'checkbox3']).should('not.be.checked')
|
||||
// .uncheck() accepts an array of values
|
||||
cy.get('.action-check [type="checkbox"]')
|
||||
.check(["checkbox1", "checkbox3"])
|
||||
.uncheck(["checkbox1", "checkbox3"])
|
||||
.should("not.be.checked");
|
||||
|
||||
// Ignore error checking prior to unchecking
|
||||
cy.get('.action-check [disabled]')
|
||||
.uncheck({force: true}).should('not.be.checked')
|
||||
})
|
||||
// Ignore error checking prior to unchecking
|
||||
cy.get(".action-check [disabled]").uncheck({ force: true }).should("not.be.checked");
|
||||
});
|
||||
|
||||
it('.select() - select an option in a <select> element', () => {
|
||||
// https://on.cypress.io/select
|
||||
it(".select() - select an option in a <select> element", () => {
|
||||
// https://on.cypress.io/select
|
||||
|
||||
// at first, no option should be selected
|
||||
cy.get('.action-select')
|
||||
.should('have.value', '--Select a fruit--')
|
||||
// at first, no option should be selected
|
||||
cy.get(".action-select").should("have.value", "--Select a fruit--");
|
||||
|
||||
// Select option(s) with matching text content
|
||||
cy.get('.action-select').select('apples')
|
||||
// confirm the apples were selected
|
||||
// note that each value starts with "fr-" in our HTML
|
||||
cy.get('.action-select').should('have.value', 'fr-apples')
|
||||
// Select option(s) with matching text content
|
||||
cy.get(".action-select").select("apples");
|
||||
// confirm the apples were selected
|
||||
// note that each value starts with "fr-" in our HTML
|
||||
cy.get(".action-select").should("have.value", "fr-apples");
|
||||
|
||||
cy.get('.action-select-multiple')
|
||||
.select(['apples', 'oranges', 'bananas'])
|
||||
// when getting multiple values, invoke "val" method first
|
||||
.invoke('val')
|
||||
.should('deep.equal', ['fr-apples', 'fr-oranges', 'fr-bananas'])
|
||||
cy.get(".action-select-multiple")
|
||||
.select(["apples", "oranges", "bananas"])
|
||||
// when getting multiple values, invoke "val" method first
|
||||
.invoke("val")
|
||||
.should("deep.equal", ["fr-apples", "fr-oranges", "fr-bananas"]);
|
||||
|
||||
// Select option(s) with matching value
|
||||
cy.get('.action-select').select('fr-bananas')
|
||||
// can attach an assertion right away to the element
|
||||
.should('have.value', 'fr-bananas')
|
||||
// Select option(s) with matching value
|
||||
cy.get(".action-select")
|
||||
.select("fr-bananas")
|
||||
// can attach an assertion right away to the element
|
||||
.should("have.value", "fr-bananas");
|
||||
|
||||
cy.get('.action-select-multiple')
|
||||
.select(['fr-apples', 'fr-oranges', 'fr-bananas'])
|
||||
.invoke('val')
|
||||
.should('deep.equal', ['fr-apples', 'fr-oranges', 'fr-bananas'])
|
||||
cy.get(".action-select-multiple")
|
||||
.select(["fr-apples", "fr-oranges", "fr-bananas"])
|
||||
.invoke("val")
|
||||
.should("deep.equal", ["fr-apples", "fr-oranges", "fr-bananas"]);
|
||||
|
||||
// assert the selected values include oranges
|
||||
cy.get('.action-select-multiple')
|
||||
.invoke('val').should('include', 'fr-oranges')
|
||||
})
|
||||
// assert the selected values include oranges
|
||||
cy.get(".action-select-multiple").invoke("val").should("include", "fr-oranges");
|
||||
});
|
||||
|
||||
it('.scrollIntoView() - scroll an element into view', () => {
|
||||
// https://on.cypress.io/scrollintoview
|
||||
it(".scrollIntoView() - scroll an element into view", () => {
|
||||
// https://on.cypress.io/scrollintoview
|
||||
|
||||
// normally all of these buttons are hidden,
|
||||
// because they're not within
|
||||
// the viewable area of their parent
|
||||
// (we need to scroll to see them)
|
||||
cy.get('#scroll-horizontal button')
|
||||
.should('not.be.visible')
|
||||
// normally all of these buttons are hidden,
|
||||
// because they're not within
|
||||
// the viewable area of their parent
|
||||
// (we need to scroll to see them)
|
||||
cy.get("#scroll-horizontal button").should("not.be.visible");
|
||||
|
||||
// scroll the button into view, as if the user had scrolled
|
||||
cy.get('#scroll-horizontal button').scrollIntoView()
|
||||
.should('be.visible')
|
||||
// scroll the button into view, as if the user had scrolled
|
||||
cy.get("#scroll-horizontal button").scrollIntoView().should("be.visible");
|
||||
|
||||
cy.get('#scroll-vertical button')
|
||||
.should('not.be.visible')
|
||||
cy.get("#scroll-vertical button").should("not.be.visible");
|
||||
|
||||
// Cypress handles the scroll direction needed
|
||||
cy.get('#scroll-vertical button').scrollIntoView()
|
||||
.should('be.visible')
|
||||
// Cypress handles the scroll direction needed
|
||||
cy.get("#scroll-vertical button").scrollIntoView().should("be.visible");
|
||||
|
||||
cy.get('#scroll-both button')
|
||||
.should('not.be.visible')
|
||||
cy.get("#scroll-both button").should("not.be.visible");
|
||||
|
||||
// Cypress knows to scroll to the right and down
|
||||
cy.get('#scroll-both button').scrollIntoView()
|
||||
.should('be.visible')
|
||||
})
|
||||
// Cypress knows to scroll to the right and down
|
||||
cy.get("#scroll-both button").scrollIntoView().should("be.visible");
|
||||
});
|
||||
|
||||
it('.trigger() - trigger an event on a DOM element', () => {
|
||||
// https://on.cypress.io/trigger
|
||||
it(".trigger() - trigger an event on a DOM element", () => {
|
||||
// https://on.cypress.io/trigger
|
||||
|
||||
// To interact with a range input (slider)
|
||||
// we need to set its value & trigger the
|
||||
// event to signal it changed
|
||||
// To interact with a range input (slider)
|
||||
// we need to set its value & trigger the
|
||||
// event to signal it changed
|
||||
|
||||
// Here, we invoke jQuery's val() method to set
|
||||
// the value and trigger the 'change' event
|
||||
cy.get('.trigger-input-range')
|
||||
.invoke('val', 25)
|
||||
.trigger('change')
|
||||
.get('input[type=range]').siblings('p')
|
||||
.should('have.text', '25')
|
||||
})
|
||||
// Here, we invoke jQuery's val() method to set
|
||||
// the value and trigger the 'change' event
|
||||
cy.get(".trigger-input-range")
|
||||
.invoke("val", 25)
|
||||
.trigger("change")
|
||||
.get("input[type=range]")
|
||||
.siblings("p")
|
||||
.should("have.text", "25");
|
||||
});
|
||||
|
||||
it('cy.scrollTo() - scroll the window or element to a position', () => {
|
||||
// https://on.cypress.io/scrollto
|
||||
it("cy.scrollTo() - scroll the window or element to a position", () => {
|
||||
// https://on.cypress.io/scrollto
|
||||
|
||||
// You can scroll to 9 specific positions of an element:
|
||||
// -----------------------------------
|
||||
// | topLeft top topRight |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | left center right |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | bottomLeft bottom bottomRight |
|
||||
// -----------------------------------
|
||||
// You can scroll to 9 specific positions of an element:
|
||||
// -----------------------------------
|
||||
// | topLeft top topRight |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | left center right |
|
||||
// | |
|
||||
// | |
|
||||
// | |
|
||||
// | bottomLeft bottom bottomRight |
|
||||
// -----------------------------------
|
||||
|
||||
// if you chain .scrollTo() off of cy, we will
|
||||
// scroll the entire window
|
||||
cy.scrollTo('bottom')
|
||||
// if you chain .scrollTo() off of cy, we will
|
||||
// scroll the entire window
|
||||
cy.scrollTo("bottom");
|
||||
|
||||
cy.get('#scrollable-horizontal').scrollTo('right')
|
||||
cy.get("#scrollable-horizontal").scrollTo("right");
|
||||
|
||||
// or you can scroll to a specific coordinate:
|
||||
// (x axis, y axis) in pixels
|
||||
cy.get('#scrollable-vertical').scrollTo(250, 250)
|
||||
// or you can scroll to a specific coordinate:
|
||||
// (x axis, y axis) in pixels
|
||||
cy.get("#scrollable-vertical").scrollTo(250, 250);
|
||||
|
||||
// or you can scroll to a specific percentage
|
||||
// of the (width, height) of the element
|
||||
cy.get('#scrollable-both').scrollTo('75%', '25%')
|
||||
// or you can scroll to a specific percentage
|
||||
// of the (width, height) of the element
|
||||
cy.get("#scrollable-both").scrollTo("75%", "25%");
|
||||
|
||||
// control the easing of the scroll (default is 'swing')
|
||||
cy.get('#scrollable-vertical').scrollTo('center', {easing: 'linear'})
|
||||
// control the easing of the scroll (default is 'swing')
|
||||
cy.get("#scrollable-vertical").scrollTo("center", { easing: "linear" });
|
||||
|
||||
// control the duration of the scroll (in ms)
|
||||
cy.get('#scrollable-both').scrollTo('center', {duration: 2000})
|
||||
})
|
||||
})
|
||||
// control the duration of the scroll (in ms)
|
||||
cy.get("#scrollable-both").scrollTo("center", { duration: 2000 });
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,39 +1,35 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Aliasing', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/aliasing')
|
||||
})
|
||||
context("Aliasing", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/aliasing");
|
||||
});
|
||||
|
||||
it('.as() - alias a DOM element for later use', () => {
|
||||
// https://on.cypress.io/as
|
||||
it(".as() - alias a DOM element for later use", () => {
|
||||
// https://on.cypress.io/as
|
||||
|
||||
// Alias a DOM element for use later
|
||||
// We don't have to traverse to the element
|
||||
// later in our code, we reference it with @
|
||||
// Alias a DOM element for use later
|
||||
// We don't have to traverse to the element
|
||||
// later in our code, we reference it with @
|
||||
|
||||
cy.get('.as-table').find('tbody>tr')
|
||||
.first().find('td').first()
|
||||
.find('button').as('firstBtn')
|
||||
cy.get(".as-table").find("tbody>tr").first().find("td").first().find("button").as("firstBtn");
|
||||
|
||||
// when we reference the alias, we place an
|
||||
// @ in front of its name
|
||||
cy.get('@firstBtn').click()
|
||||
// when we reference the alias, we place an
|
||||
// @ in front of its name
|
||||
cy.get("@firstBtn").click();
|
||||
|
||||
cy.get('@firstBtn')
|
||||
.should('have.class', 'btn-success')
|
||||
.and('contain', 'Changed')
|
||||
})
|
||||
cy.get("@firstBtn").should("have.class", "btn-success").and("contain", "Changed");
|
||||
});
|
||||
|
||||
it('.as() - alias a route for later use', () => {
|
||||
// Alias the route to wait for its response
|
||||
cy.intercept('GET', '**/comments/*').as('getComment')
|
||||
it(".as() - alias a route for later use", () => {
|
||||
// Alias the route to wait for its response
|
||||
cy.intercept("GET", "**/comments/*").as("getComment");
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-btn').click()
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get(".network-btn").click();
|
||||
|
||||
// https://on.cypress.io/wait
|
||||
cy.wait('@getComment').its('response.statusCode').should('eq', 200)
|
||||
})
|
||||
})
|
||||
// https://on.cypress.io/wait
|
||||
cy.wait("@getComment").its("response.statusCode").should("eq", 200);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,177 +1,173 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Assertions', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/assertions')
|
||||
})
|
||||
context("Assertions", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/assertions");
|
||||
});
|
||||
|
||||
describe('Implicit Assertions', () => {
|
||||
it('.should() - make an assertion about the current subject', () => {
|
||||
// https://on.cypress.io/should
|
||||
cy.get('.assertion-table')
|
||||
.find('tbody tr:last')
|
||||
.should('have.class', 'success')
|
||||
.find('td')
|
||||
.first()
|
||||
// checking the text of the <td> element in various ways
|
||||
.should('have.text', 'Column content')
|
||||
.should('contain', 'Column content')
|
||||
.should('have.html', 'Column content')
|
||||
// chai-jquery uses "is()" to check if element matches selector
|
||||
.should('match', 'td')
|
||||
// to match text content against a regular expression
|
||||
// first need to invoke jQuery method text()
|
||||
// and then match using regular expression
|
||||
.invoke('text')
|
||||
.should('match', /column content/i)
|
||||
describe("Implicit Assertions", () => {
|
||||
it(".should() - make an assertion about the current subject", () => {
|
||||
// https://on.cypress.io/should
|
||||
cy.get(".assertion-table")
|
||||
.find("tbody tr:last")
|
||||
.should("have.class", "success")
|
||||
.find("td")
|
||||
.first()
|
||||
// checking the text of the <td> element in various ways
|
||||
.should("have.text", "Column content")
|
||||
.should("contain", "Column content")
|
||||
.should("have.html", "Column content")
|
||||
// chai-jquery uses "is()" to check if element matches selector
|
||||
.should("match", "td")
|
||||
// to match text content against a regular expression
|
||||
// first need to invoke jQuery method text()
|
||||
// and then match using regular expression
|
||||
.invoke("text")
|
||||
.should("match", /column content/i);
|
||||
|
||||
// a better way to check element's text content against a regular expression
|
||||
// is to use "cy.contains"
|
||||
// https://on.cypress.io/contains
|
||||
cy.get('.assertion-table')
|
||||
.find('tbody tr:last')
|
||||
// finds first <td> element with text content matching regular expression
|
||||
.contains('td', /column content/i)
|
||||
.should('be.visible')
|
||||
// a better way to check element's text content against a regular expression
|
||||
// is to use "cy.contains"
|
||||
// https://on.cypress.io/contains
|
||||
cy.get(".assertion-table")
|
||||
.find("tbody tr:last")
|
||||
// finds first <td> element with text content matching regular expression
|
||||
.contains("td", /column content/i)
|
||||
.should("be.visible");
|
||||
|
||||
// for more information about asserting element's text
|
||||
// see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents
|
||||
// for more information about asserting element's text
|
||||
// see https://on.cypress.io/using-cypress-faq#How-do-I-get-an-element’s-text-contents
|
||||
});
|
||||
|
||||
it(".and() - chain multiple assertions together", () => {
|
||||
// https://on.cypress.io/and
|
||||
cy.get(".assertions-link").should("have.class", "active").and("have.attr", "href").and("include", "cypress.io");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Explicit Assertions", () => {
|
||||
// https://on.cypress.io/assertions
|
||||
it("expect - make an assertion about a specified subject", () => {
|
||||
// We can use Chai's BDD style assertions
|
||||
expect(true).to.be.true;
|
||||
const o = { foo: "bar" };
|
||||
|
||||
expect(o).to.equal(o);
|
||||
expect(o).to.deep.equal({ foo: "bar" });
|
||||
// matching text using regular expression
|
||||
expect("FooBar").to.match(/bar$/i);
|
||||
});
|
||||
|
||||
it("pass your own callback function to should()", () => {
|
||||
// Pass a function to should that can have any number
|
||||
// of explicit assertions within it.
|
||||
// The ".should(cb)" function will be retried
|
||||
// automatically until it passes all your explicit assertions or times out.
|
||||
cy.get(".assertions-p")
|
||||
.find("p")
|
||||
.should(($p) => {
|
||||
// https://on.cypress.io/$
|
||||
// return an array of texts from all of the p's
|
||||
// @ts-ignore TS6133 unused variable
|
||||
const texts = $p.map((i, el) => Cypress.$(el).text());
|
||||
|
||||
// jquery map returns jquery object
|
||||
// and .get() convert this to simple array
|
||||
const paragraphs = texts.get();
|
||||
|
||||
// array should have length of 3
|
||||
expect(paragraphs, "has 3 paragraphs").to.have.length(3);
|
||||
|
||||
// use second argument to expect(...) to provide clear
|
||||
// message with each assertion
|
||||
expect(paragraphs, "has expected text in each paragraph").to.deep.eq([
|
||||
"Some text from first p",
|
||||
"More text from second p",
|
||||
"And even more text from third p"
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
it("finds element by class name regex", () => {
|
||||
cy.get(".docs-header")
|
||||
.find("div")
|
||||
// .should(cb) callback function will be retried
|
||||
.should(($div) => {
|
||||
expect($div).to.have.length(1);
|
||||
|
||||
const className = $div[0].className;
|
||||
|
||||
expect(className).to.match(/heading-/);
|
||||
})
|
||||
// .then(cb) callback is not retried,
|
||||
// it either passes or fails
|
||||
.then(($div) => {
|
||||
expect($div, "text content").to.have.text("Introduction");
|
||||
});
|
||||
});
|
||||
|
||||
it('.and() - chain multiple assertions together', () => {
|
||||
// https://on.cypress.io/and
|
||||
cy.get('.assertions-link')
|
||||
.should('have.class', 'active')
|
||||
.and('have.attr', 'href')
|
||||
.and('include', 'cypress.io')
|
||||
})
|
||||
})
|
||||
it("can throw any error", () => {
|
||||
cy.get(".docs-header")
|
||||
.find("div")
|
||||
.should(($div) => {
|
||||
if ($div.length !== 1) {
|
||||
// you can throw your own errors
|
||||
throw new Error("Did not find 1 element");
|
||||
}
|
||||
|
||||
describe('Explicit Assertions', () => {
|
||||
// https://on.cypress.io/assertions
|
||||
it('expect - make an assertion about a specified subject', () => {
|
||||
// We can use Chai's BDD style assertions
|
||||
expect(true).to.be.true
|
||||
const o = {foo: 'bar'}
|
||||
const className = $div[0].className;
|
||||
|
||||
expect(o).to.equal(o)
|
||||
expect(o).to.deep.equal({foo: 'bar'})
|
||||
// matching text using regular expression
|
||||
expect('FooBar').to.match(/bar$/i)
|
||||
})
|
||||
if (!className.match(/heading-/)) {
|
||||
throw new Error(`Could not find class "heading-" in ${className}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('pass your own callback function to should()', () => {
|
||||
// Pass a function to should that can have any number
|
||||
// of explicit assertions within it.
|
||||
// The ".should(cb)" function will be retried
|
||||
// automatically until it passes all your explicit assertions or times out.
|
||||
cy.get('.assertions-p')
|
||||
.find('p')
|
||||
.should(($p) => {
|
||||
// https://on.cypress.io/$
|
||||
// return an array of texts from all of the p's
|
||||
// @ts-ignore TS6133 unused variable
|
||||
const texts = $p.map((i, el) => Cypress.$(el).text())
|
||||
it("matches unknown text between two elements", () => {
|
||||
/**
|
||||
* Text from the first element.
|
||||
* @type {string}
|
||||
*/
|
||||
let text;
|
||||
|
||||
// jquery map returns jquery object
|
||||
// and .get() convert this to simple array
|
||||
const paragraphs = texts.get()
|
||||
/**
|
||||
* Normalizes passed text,
|
||||
* useful before comparing text with spaces and different capitalization.
|
||||
* @param {string} s Text to normalize
|
||||
*/
|
||||
const normalizeText = (s) => s.replace(/\s/g, "").toLowerCase();
|
||||
|
||||
// array should have length of 3
|
||||
expect(paragraphs, 'has 3 paragraphs').to.have.length(3)
|
||||
cy.get(".two-elements")
|
||||
.find(".first")
|
||||
.then(($first) => {
|
||||
// save text from the first element
|
||||
text = normalizeText($first.text());
|
||||
});
|
||||
|
||||
// use second argument to expect(...) to provide clear
|
||||
// message with each assertion
|
||||
expect(paragraphs, 'has expected text in each paragraph').to.deep.eq([
|
||||
'Some text from first p',
|
||||
'More text from second p',
|
||||
'And even more text from third p',
|
||||
])
|
||||
})
|
||||
})
|
||||
cy.get(".two-elements")
|
||||
.find(".second")
|
||||
.should(($div) => {
|
||||
// we can massage text before comparing
|
||||
const secondText = normalizeText($div.text());
|
||||
|
||||
it('finds element by class name regex', () => {
|
||||
cy.get('.docs-header')
|
||||
.find('div')
|
||||
// .should(cb) callback function will be retried
|
||||
.should(($div) => {
|
||||
expect($div).to.have.length(1)
|
||||
expect(secondText, "second text").to.equal(text);
|
||||
});
|
||||
});
|
||||
|
||||
const className = $div[0].className
|
||||
it("assert - assert shape of an object", () => {
|
||||
const person = {
|
||||
name: "Joe",
|
||||
age: 20
|
||||
};
|
||||
|
||||
expect(className).to.match(/heading-/)
|
||||
})
|
||||
// .then(cb) callback is not retried,
|
||||
// it either passes or fails
|
||||
.then(($div) => {
|
||||
expect($div, 'text content').to.have.text('Introduction')
|
||||
})
|
||||
})
|
||||
assert.isObject(person, "value is object");
|
||||
});
|
||||
|
||||
it('can throw any error', () => {
|
||||
cy.get('.docs-header')
|
||||
.find('div')
|
||||
.should(($div) => {
|
||||
if ($div.length !== 1) {
|
||||
// you can throw your own errors
|
||||
throw new Error('Did not find 1 element')
|
||||
}
|
||||
it("retries the should callback until assertions pass", () => {
|
||||
cy.get("#random-number").should(($div) => {
|
||||
const n = parseFloat($div.text());
|
||||
|
||||
const className = $div[0].className
|
||||
|
||||
if (!className.match(/heading-/)) {
|
||||
throw new Error(`Could not find class "heading-" in ${className}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('matches unknown text between two elements', () => {
|
||||
/**
|
||||
* Text from the first element.
|
||||
* @type {string}
|
||||
*/
|
||||
let text
|
||||
|
||||
/**
|
||||
* Normalizes passed text,
|
||||
* useful before comparing text with spaces and different capitalization.
|
||||
* @param {string} s Text to normalize
|
||||
*/
|
||||
const normalizeText = (s) => s.replace(/\s/g, '').toLowerCase()
|
||||
|
||||
cy.get('.two-elements')
|
||||
.find('.first')
|
||||
.then(($first) => {
|
||||
// save text from the first element
|
||||
text = normalizeText($first.text())
|
||||
})
|
||||
|
||||
cy.get('.two-elements')
|
||||
.find('.second')
|
||||
.should(($div) => {
|
||||
// we can massage text before comparing
|
||||
const secondText = normalizeText($div.text())
|
||||
|
||||
expect(secondText, 'second text').to.equal(text)
|
||||
})
|
||||
})
|
||||
|
||||
it('assert - assert shape of an object', () => {
|
||||
const person = {
|
||||
name: 'Joe',
|
||||
age: 20,
|
||||
}
|
||||
|
||||
assert.isObject(person, 'value is object')
|
||||
})
|
||||
|
||||
it('retries the should callback until assertions pass', () => {
|
||||
cy.get('#random-number')
|
||||
.should(($div) => {
|
||||
const n = parseFloat($div.text())
|
||||
|
||||
expect(n).to.be.gte(1).and.be.lte(10)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
expect(n).to.be.gte(1).and.be.lte(10);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,97 +1,96 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Connectors', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/connectors')
|
||||
})
|
||||
context("Connectors", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/connectors");
|
||||
});
|
||||
|
||||
it('.each() - iterate over an array of elements', () => {
|
||||
// https://on.cypress.io/each
|
||||
cy.get('.connectors-each-ul>li')
|
||||
.each(($el, index, $list) => {
|
||||
console.log($el, index, $list)
|
||||
})
|
||||
})
|
||||
it(".each() - iterate over an array of elements", () => {
|
||||
// https://on.cypress.io/each
|
||||
cy.get(".connectors-each-ul>li").each(($el, index, $list) => {
|
||||
console.log($el, index, $list);
|
||||
});
|
||||
});
|
||||
|
||||
it('.its() - get properties on the current subject', () => {
|
||||
// https://on.cypress.io/its
|
||||
cy.get('.connectors-its-ul>li')
|
||||
// calls the 'length' property yielding that value
|
||||
.its('length')
|
||||
.should('be.gt', 2)
|
||||
})
|
||||
it(".its() - get properties on the current subject", () => {
|
||||
// https://on.cypress.io/its
|
||||
cy.get(".connectors-its-ul>li")
|
||||
// calls the 'length' property yielding that value
|
||||
.its("length")
|
||||
.should("be.gt", 2);
|
||||
});
|
||||
|
||||
it('.invoke() - invoke a function on the current subject', () => {
|
||||
// our div is hidden in our script.js
|
||||
// $('.connectors-div').hide()
|
||||
it(".invoke() - invoke a function on the current subject", () => {
|
||||
// our div is hidden in our script.js
|
||||
// $('.connectors-div').hide()
|
||||
|
||||
// https://on.cypress.io/invoke
|
||||
cy.get('.connectors-div').should('be.hidden')
|
||||
// call the jquery method 'show' on the 'div.container'
|
||||
.invoke('show')
|
||||
.should('be.visible')
|
||||
})
|
||||
// https://on.cypress.io/invoke
|
||||
cy.get(".connectors-div")
|
||||
.should("be.hidden")
|
||||
// call the jquery method 'show' on the 'div.container'
|
||||
.invoke("show")
|
||||
.should("be.visible");
|
||||
});
|
||||
|
||||
it('.spread() - spread an array as individual args to callback function', () => {
|
||||
// https://on.cypress.io/spread
|
||||
const arr = ['foo', 'bar', 'baz']
|
||||
it(".spread() - spread an array as individual args to callback function", () => {
|
||||
// https://on.cypress.io/spread
|
||||
const arr = ["foo", "bar", "baz"];
|
||||
|
||||
cy.wrap(arr).spread((foo, bar, baz) => {
|
||||
expect(foo).to.eq('foo')
|
||||
expect(bar).to.eq('bar')
|
||||
expect(baz).to.eq('baz')
|
||||
cy.wrap(arr).spread((foo, bar, baz) => {
|
||||
expect(foo).to.eq("foo");
|
||||
expect(bar).to.eq("bar");
|
||||
expect(baz).to.eq("baz");
|
||||
});
|
||||
});
|
||||
|
||||
describe(".then()", () => {
|
||||
it("invokes a callback function with the current subject", () => {
|
||||
// https://on.cypress.io/then
|
||||
cy.get(".connectors-list > li").then(($lis) => {
|
||||
expect($lis, "3 items").to.have.length(3);
|
||||
expect($lis.eq(0), "first item").to.contain("Walk the dog");
|
||||
expect($lis.eq(1), "second item").to.contain("Feed the cat");
|
||||
expect($lis.eq(2), "third item").to.contain("Write JavaScript");
|
||||
});
|
||||
});
|
||||
|
||||
it("yields the returned value to the next command", () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1);
|
||||
|
||||
return 2;
|
||||
})
|
||||
})
|
||||
.then((num) => {
|
||||
expect(num).to.equal(2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('.then()', () => {
|
||||
it('invokes a callback function with the current subject', () => {
|
||||
// https://on.cypress.io/then
|
||||
cy.get('.connectors-list > li')
|
||||
.then(($lis) => {
|
||||
expect($lis, '3 items').to.have.length(3)
|
||||
expect($lis.eq(0), 'first item').to.contain('Walk the dog')
|
||||
expect($lis.eq(1), 'second item').to.contain('Feed the cat')
|
||||
expect($lis.eq(2), 'third item').to.contain('Write JavaScript')
|
||||
})
|
||||
it("yields the original subject without return", () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1);
|
||||
// note that nothing is returned from this callback
|
||||
})
|
||||
.then((num) => {
|
||||
// this callback receives the original unchanged value 1
|
||||
expect(num).to.equal(1);
|
||||
});
|
||||
});
|
||||
|
||||
it('yields the returned value to the next command', () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1)
|
||||
|
||||
return 2
|
||||
})
|
||||
.then((num) => {
|
||||
expect(num).to.equal(2)
|
||||
})
|
||||
it("yields the value yielded by the last Cypress command inside", () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1);
|
||||
// note how we run a Cypress command
|
||||
// the result yielded by this Cypress command
|
||||
// will be passed to the second ".then"
|
||||
cy.wrap(2);
|
||||
})
|
||||
|
||||
it('yields the original subject without return', () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1)
|
||||
// note that nothing is returned from this callback
|
||||
})
|
||||
.then((num) => {
|
||||
// this callback receives the original unchanged value 1
|
||||
expect(num).to.equal(1)
|
||||
})
|
||||
})
|
||||
|
||||
it('yields the value yielded by the last Cypress command inside', () => {
|
||||
cy.wrap(1)
|
||||
.then((num) => {
|
||||
expect(num).to.equal(1)
|
||||
// note how we run a Cypress command
|
||||
// the result yielded by this Cypress command
|
||||
// will be passed to the second ".then"
|
||||
cy.wrap(2)
|
||||
})
|
||||
.then((num) => {
|
||||
// this callback receives the value yielded by "cy.wrap(2)"
|
||||
expect(num).to.equal(2)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
.then((num) => {
|
||||
// this callback receives the value yielded by "cy.wrap(2)"
|
||||
expect(num).to.equal(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,77 +1,79 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Cookies', () => {
|
||||
beforeEach(() => {
|
||||
Cypress.Cookies.debug(true)
|
||||
context("Cookies", () => {
|
||||
beforeEach(() => {
|
||||
Cypress.Cookies.debug(true);
|
||||
|
||||
cy.visit('https://example.cypress.io/commands/cookies')
|
||||
cy.visit("https://example.cypress.io/commands/cookies");
|
||||
|
||||
// clear cookies again after visiting to remove
|
||||
// any 3rd party cookies picked up such as cloudflare
|
||||
cy.clearCookies()
|
||||
})
|
||||
// clear cookies again after visiting to remove
|
||||
// any 3rd party cookies picked up such as cloudflare
|
||||
cy.clearCookies();
|
||||
});
|
||||
|
||||
it('cy.getCookie() - get a browser cookie', () => {
|
||||
// https://on.cypress.io/getcookie
|
||||
cy.get('#getCookie .set-a-cookie').click()
|
||||
it("cy.getCookie() - get a browser cookie", () => {
|
||||
// https://on.cypress.io/getcookie
|
||||
cy.get("#getCookie .set-a-cookie").click();
|
||||
|
||||
// cy.getCookie() yields a cookie object
|
||||
cy.getCookie('token').should('have.property', 'value', '123ABC')
|
||||
})
|
||||
// cy.getCookie() yields a cookie object
|
||||
cy.getCookie("token").should("have.property", "value", "123ABC");
|
||||
});
|
||||
|
||||
it('cy.getCookies() - get browser cookies', () => {
|
||||
// https://on.cypress.io/getcookies
|
||||
cy.getCookies().should('be.empty')
|
||||
it("cy.getCookies() - get browser cookies", () => {
|
||||
// https://on.cypress.io/getcookies
|
||||
cy.getCookies().should("be.empty");
|
||||
|
||||
cy.get('#getCookies .set-a-cookie').click()
|
||||
cy.get("#getCookies .set-a-cookie").click();
|
||||
|
||||
// cy.getCookies() yields an array of cookies
|
||||
cy.getCookies().should('have.length', 1).should((cookies) => {
|
||||
// each cookie has these properties
|
||||
expect(cookies[0]).to.have.property('name', 'token')
|
||||
expect(cookies[0]).to.have.property('value', '123ABC')
|
||||
expect(cookies[0]).to.have.property('httpOnly', false)
|
||||
expect(cookies[0]).to.have.property('secure', false)
|
||||
expect(cookies[0]).to.have.property('domain')
|
||||
expect(cookies[0]).to.have.property('path')
|
||||
})
|
||||
})
|
||||
// cy.getCookies() yields an array of cookies
|
||||
cy.getCookies()
|
||||
.should("have.length", 1)
|
||||
.should((cookies) => {
|
||||
// each cookie has these properties
|
||||
expect(cookies[0]).to.have.property("name", "token");
|
||||
expect(cookies[0]).to.have.property("value", "123ABC");
|
||||
expect(cookies[0]).to.have.property("httpOnly", false);
|
||||
expect(cookies[0]).to.have.property("secure", false);
|
||||
expect(cookies[0]).to.have.property("domain");
|
||||
expect(cookies[0]).to.have.property("path");
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.setCookie() - set a browser cookie', () => {
|
||||
// https://on.cypress.io/setcookie
|
||||
cy.getCookies().should('be.empty')
|
||||
it("cy.setCookie() - set a browser cookie", () => {
|
||||
// https://on.cypress.io/setcookie
|
||||
cy.getCookies().should("be.empty");
|
||||
|
||||
cy.setCookie('foo', 'bar')
|
||||
cy.setCookie("foo", "bar");
|
||||
|
||||
// cy.getCookie() yields a cookie object
|
||||
cy.getCookie('foo').should('have.property', 'value', 'bar')
|
||||
})
|
||||
// cy.getCookie() yields a cookie object
|
||||
cy.getCookie("foo").should("have.property", "value", "bar");
|
||||
});
|
||||
|
||||
it('cy.clearCookie() - clear a browser cookie', () => {
|
||||
// https://on.cypress.io/clearcookie
|
||||
cy.getCookie('token').should('be.null')
|
||||
it("cy.clearCookie() - clear a browser cookie", () => {
|
||||
// https://on.cypress.io/clearcookie
|
||||
cy.getCookie("token").should("be.null");
|
||||
|
||||
cy.get('#clearCookie .set-a-cookie').click()
|
||||
cy.get("#clearCookie .set-a-cookie").click();
|
||||
|
||||
cy.getCookie('token').should('have.property', 'value', '123ABC')
|
||||
cy.getCookie("token").should("have.property", "value", "123ABC");
|
||||
|
||||
// cy.clearCookies() yields null
|
||||
cy.clearCookie('token').should('be.null')
|
||||
// cy.clearCookies() yields null
|
||||
cy.clearCookie("token").should("be.null");
|
||||
|
||||
cy.getCookie('token').should('be.null')
|
||||
})
|
||||
cy.getCookie("token").should("be.null");
|
||||
});
|
||||
|
||||
it('cy.clearCookies() - clear browser cookies', () => {
|
||||
// https://on.cypress.io/clearcookies
|
||||
cy.getCookies().should('be.empty')
|
||||
it("cy.clearCookies() - clear browser cookies", () => {
|
||||
// https://on.cypress.io/clearcookies
|
||||
cy.getCookies().should("be.empty");
|
||||
|
||||
cy.get('#clearCookies .set-a-cookie').click()
|
||||
cy.get("#clearCookies .set-a-cookie").click();
|
||||
|
||||
cy.getCookies().should('have.length', 1)
|
||||
cy.getCookies().should("have.length", 1);
|
||||
|
||||
// cy.clearCookies() yields null
|
||||
cy.clearCookies()
|
||||
// cy.clearCookies() yields null
|
||||
cy.clearCookies();
|
||||
|
||||
cy.getCookies().should('be.empty')
|
||||
})
|
||||
})
|
||||
cy.getCookies().should("be.empty");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,202 +1,208 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Cypress.Commands', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.Commands", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
// https://on.cypress.io/custom-commands
|
||||
// https://on.cypress.io/custom-commands
|
||||
|
||||
it('.add() - create a custom command', () => {
|
||||
Cypress.Commands.add('console', {
|
||||
prevSubject: true,
|
||||
}, (subject, method) => {
|
||||
// the previous subject is automatically received
|
||||
// and the commands arguments are shifted
|
||||
it(".add() - create a custom command", () => {
|
||||
Cypress.Commands.add(
|
||||
"console",
|
||||
{
|
||||
prevSubject: true
|
||||
},
|
||||
(subject, method) => {
|
||||
// the previous subject is automatically received
|
||||
// and the commands arguments are shifted
|
||||
|
||||
// allow us to change the console method used
|
||||
method = method || 'log'
|
||||
// allow us to change the console method used
|
||||
method = method || "log";
|
||||
|
||||
// log the subject to the console
|
||||
// @ts-ignore TS7017
|
||||
console[method]('The subject is', subject)
|
||||
// log the subject to the console
|
||||
// @ts-ignore TS7017
|
||||
console[method]("The subject is", subject);
|
||||
|
||||
// whatever we return becomes the new subject
|
||||
// we don't want to change the subject so
|
||||
// we return whatever was passed in
|
||||
return subject
|
||||
})
|
||||
// whatever we return becomes the new subject
|
||||
// we don't want to change the subject so
|
||||
// we return whatever was passed in
|
||||
return subject;
|
||||
}
|
||||
);
|
||||
|
||||
// @ts-ignore TS2339
|
||||
cy.get('button').console('info').then(($button) => {
|
||||
// subject is still $button
|
||||
})
|
||||
})
|
||||
})
|
||||
// @ts-ignore TS2339
|
||||
cy.get("button")
|
||||
.console("info")
|
||||
.then(($button) => {
|
||||
// subject is still $button
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.Cookies', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.Cookies", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
// https://on.cypress.io/cookies
|
||||
it('.debug() - enable or disable debugging', () => {
|
||||
Cypress.Cookies.debug(true)
|
||||
// https://on.cypress.io/cookies
|
||||
it(".debug() - enable or disable debugging", () => {
|
||||
Cypress.Cookies.debug(true);
|
||||
|
||||
// Cypress will now log in the console when
|
||||
// cookies are set or cleared
|
||||
cy.setCookie('fakeCookie', '123ABC')
|
||||
cy.clearCookie('fakeCookie')
|
||||
cy.setCookie('fakeCookie', '123ABC')
|
||||
cy.clearCookie('fakeCookie')
|
||||
cy.setCookie('fakeCookie', '123ABC')
|
||||
})
|
||||
// Cypress will now log in the console when
|
||||
// cookies are set or cleared
|
||||
cy.setCookie("fakeCookie", "123ABC");
|
||||
cy.clearCookie("fakeCookie");
|
||||
cy.setCookie("fakeCookie", "123ABC");
|
||||
cy.clearCookie("fakeCookie");
|
||||
cy.setCookie("fakeCookie", "123ABC");
|
||||
});
|
||||
|
||||
it('.preserveOnce() - preserve cookies by key', () => {
|
||||
// normally cookies are reset after each test
|
||||
cy.getCookie('fakeCookie').should('not.be.ok')
|
||||
it(".preserveOnce() - preserve cookies by key", () => {
|
||||
// normally cookies are reset after each test
|
||||
cy.getCookie("fakeCookie").should("not.be.ok");
|
||||
|
||||
// preserving a cookie will not clear it when
|
||||
// the next test starts
|
||||
cy.setCookie('lastCookie', '789XYZ')
|
||||
Cypress.Cookies.preserveOnce('lastCookie')
|
||||
})
|
||||
// preserving a cookie will not clear it when
|
||||
// the next test starts
|
||||
cy.setCookie("lastCookie", "789XYZ");
|
||||
Cypress.Cookies.preserveOnce("lastCookie");
|
||||
});
|
||||
|
||||
it('.defaults() - set defaults for all cookies', () => {
|
||||
// now any cookie with the name 'session_id' will
|
||||
// not be cleared before each new test runs
|
||||
Cypress.Cookies.defaults({
|
||||
preserve: 'session_id',
|
||||
})
|
||||
})
|
||||
})
|
||||
it(".defaults() - set defaults for all cookies", () => {
|
||||
// now any cookie with the name 'session_id' will
|
||||
// not be cleared before each new test runs
|
||||
Cypress.Cookies.defaults({
|
||||
preserve: "session_id"
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.arch', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.arch", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
it('Get CPU architecture name of underlying OS', () => {
|
||||
// https://on.cypress.io/arch
|
||||
expect(Cypress.arch).to.exist
|
||||
})
|
||||
})
|
||||
it("Get CPU architecture name of underlying OS", () => {
|
||||
// https://on.cypress.io/arch
|
||||
expect(Cypress.arch).to.exist;
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.config()', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.config()", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
it('Get and set configuration options', () => {
|
||||
// https://on.cypress.io/config
|
||||
let myConfig = Cypress.config()
|
||||
it("Get and set configuration options", () => {
|
||||
// https://on.cypress.io/config
|
||||
let myConfig = Cypress.config();
|
||||
|
||||
expect(myConfig).to.have.property('animationDistanceThreshold', 5)
|
||||
expect(myConfig).to.have.property('baseUrl', null)
|
||||
expect(myConfig).to.have.property('defaultCommandTimeout', 4000)
|
||||
expect(myConfig).to.have.property('requestTimeout', 5000)
|
||||
expect(myConfig).to.have.property('responseTimeout', 30000)
|
||||
expect(myConfig).to.have.property('viewportHeight', 660)
|
||||
expect(myConfig).to.have.property('viewportWidth', 1000)
|
||||
expect(myConfig).to.have.property('pageLoadTimeout', 60000)
|
||||
expect(myConfig).to.have.property('waitForAnimations', true)
|
||||
expect(myConfig).to.have.property("animationDistanceThreshold", 5);
|
||||
expect(myConfig).to.have.property("baseUrl", null);
|
||||
expect(myConfig).to.have.property("defaultCommandTimeout", 4000);
|
||||
expect(myConfig).to.have.property("requestTimeout", 5000);
|
||||
expect(myConfig).to.have.property("responseTimeout", 30000);
|
||||
expect(myConfig).to.have.property("viewportHeight", 660);
|
||||
expect(myConfig).to.have.property("viewportWidth", 1000);
|
||||
expect(myConfig).to.have.property("pageLoadTimeout", 60000);
|
||||
expect(myConfig).to.have.property("waitForAnimations", true);
|
||||
|
||||
expect(Cypress.config('pageLoadTimeout')).to.eq(60000)
|
||||
expect(Cypress.config("pageLoadTimeout")).to.eq(60000);
|
||||
|
||||
// this will change the config for the rest of your tests!
|
||||
Cypress.config('pageLoadTimeout', 20000)
|
||||
// this will change the config for the rest of your tests!
|
||||
Cypress.config("pageLoadTimeout", 20000);
|
||||
|
||||
expect(Cypress.config('pageLoadTimeout')).to.eq(20000)
|
||||
expect(Cypress.config("pageLoadTimeout")).to.eq(20000);
|
||||
|
||||
Cypress.config('pageLoadTimeout', 60000)
|
||||
})
|
||||
})
|
||||
Cypress.config("pageLoadTimeout", 60000);
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.dom', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.dom", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
// https://on.cypress.io/dom
|
||||
it('.isHidden() - determine if a DOM element is hidden', () => {
|
||||
let hiddenP = Cypress.$('.dom-p p.hidden').get(0)
|
||||
let visibleP = Cypress.$('.dom-p p.visible').get(0)
|
||||
// https://on.cypress.io/dom
|
||||
it(".isHidden() - determine if a DOM element is hidden", () => {
|
||||
let hiddenP = Cypress.$(".dom-p p.hidden").get(0);
|
||||
let visibleP = Cypress.$(".dom-p p.visible").get(0);
|
||||
|
||||
// our first paragraph has css class 'hidden'
|
||||
expect(Cypress.dom.isHidden(hiddenP)).to.be.true
|
||||
expect(Cypress.dom.isHidden(visibleP)).to.be.false
|
||||
})
|
||||
})
|
||||
// our first paragraph has css class 'hidden'
|
||||
expect(Cypress.dom.isHidden(hiddenP)).to.be.true;
|
||||
expect(Cypress.dom.isHidden(visibleP)).to.be.false;
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.env()', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.env()", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
// We can set environment variables for highly dynamic values
|
||||
// We can set environment variables for highly dynamic values
|
||||
|
||||
// https://on.cypress.io/environment-variables
|
||||
it('Get environment variables', () => {
|
||||
// https://on.cypress.io/env
|
||||
// set multiple environment variables
|
||||
Cypress.env({
|
||||
host: 'veronica.dev.local',
|
||||
api_server: 'http://localhost:8888/v1/',
|
||||
})
|
||||
// https://on.cypress.io/environment-variables
|
||||
it("Get environment variables", () => {
|
||||
// https://on.cypress.io/env
|
||||
// set multiple environment variables
|
||||
Cypress.env({
|
||||
host: "veronica.dev.local",
|
||||
api_server: "http://localhost:8888/v1/"
|
||||
});
|
||||
|
||||
// get environment variable
|
||||
expect(Cypress.env('host')).to.eq('veronica.dev.local')
|
||||
// get environment variable
|
||||
expect(Cypress.env("host")).to.eq("veronica.dev.local");
|
||||
|
||||
// set environment variable
|
||||
Cypress.env('api_server', 'http://localhost:8888/v2/')
|
||||
expect(Cypress.env('api_server')).to.eq('http://localhost:8888/v2/')
|
||||
// set environment variable
|
||||
Cypress.env("api_server", "http://localhost:8888/v2/");
|
||||
expect(Cypress.env("api_server")).to.eq("http://localhost:8888/v2/");
|
||||
|
||||
// get all environment variable
|
||||
expect(Cypress.env()).to.have.property('host', 'veronica.dev.local')
|
||||
expect(Cypress.env()).to.have.property('api_server', 'http://localhost:8888/v2/')
|
||||
})
|
||||
})
|
||||
// get all environment variable
|
||||
expect(Cypress.env()).to.have.property("host", "veronica.dev.local");
|
||||
expect(Cypress.env()).to.have.property("api_server", "http://localhost:8888/v2/");
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.log', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.log", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
it('Control what is printed to the Command Log', () => {
|
||||
// https://on.cypress.io/cypress-log
|
||||
})
|
||||
})
|
||||
it("Control what is printed to the Command Log", () => {
|
||||
// https://on.cypress.io/cypress-log
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.platform', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.platform", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
it('Get underlying OS name', () => {
|
||||
// https://on.cypress.io/platform
|
||||
expect(Cypress.platform).to.be.exist
|
||||
})
|
||||
})
|
||||
it("Get underlying OS name", () => {
|
||||
// https://on.cypress.io/platform
|
||||
expect(Cypress.platform).to.be.exist;
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.version', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.version", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
it('Get current version of Cypress being run', () => {
|
||||
// https://on.cypress.io/version
|
||||
expect(Cypress.version).to.be.exist
|
||||
})
|
||||
})
|
||||
it("Get current version of Cypress being run", () => {
|
||||
// https://on.cypress.io/version
|
||||
expect(Cypress.version).to.be.exist;
|
||||
});
|
||||
});
|
||||
|
||||
context('Cypress.spec', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/cypress-api')
|
||||
})
|
||||
context("Cypress.spec", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/cypress-api");
|
||||
});
|
||||
|
||||
it('Get current spec information', () => {
|
||||
// https://on.cypress.io/spec
|
||||
// wrap the object so we can inspect it easily by clicking in the command log
|
||||
cy.wrap(Cypress.spec).should('include.keys', ['name', 'relative', 'absolute'])
|
||||
})
|
||||
})
|
||||
it("Get current spec information", () => {
|
||||
// https://on.cypress.io/spec
|
||||
// wrap the object so we can inspect it easily by clicking in the command log
|
||||
cy.wrap(Cypress.spec).should("include.keys", ["name", "relative", "absolute"]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -3,86 +3,84 @@
|
||||
/// JSON fixture file can be loaded directly using
|
||||
// the built-in JavaScript bundler
|
||||
// @ts-ignore
|
||||
const requiredExample = require('../../fixtures/example')
|
||||
const requiredExample = require("../../fixtures/example");
|
||||
|
||||
context('Files', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/files')
|
||||
})
|
||||
context("Files", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/files");
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
// load example.json fixture file and store
|
||||
// in the test context object
|
||||
cy.fixture('example.json').as('example')
|
||||
})
|
||||
beforeEach(() => {
|
||||
// load example.json fixture file and store
|
||||
// in the test context object
|
||||
cy.fixture("example.json").as("example");
|
||||
});
|
||||
|
||||
it('cy.fixture() - load a fixture', () => {
|
||||
// https://on.cypress.io/fixture
|
||||
it("cy.fixture() - load a fixture", () => {
|
||||
// https://on.cypress.io/fixture
|
||||
|
||||
// Instead of writing a response inline you can
|
||||
// use a fixture file's content.
|
||||
// Instead of writing a response inline you can
|
||||
// use a fixture file's content.
|
||||
|
||||
// when application makes an Ajax request matching "GET **/comments/*"
|
||||
// Cypress will intercept it and reply with the object in `example.json` fixture
|
||||
cy.intercept('GET', '**/comments/*', {fixture: 'example.json'}).as('getComment')
|
||||
// when application makes an Ajax request matching "GET **/comments/*"
|
||||
// Cypress will intercept it and reply with the object in `example.json` fixture
|
||||
cy.intercept("GET", "**/comments/*", { fixture: "example.json" }).as("getComment");
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.fixture-btn').click()
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get(".fixture-btn").click();
|
||||
|
||||
cy.wait('@getComment').its('response.body')
|
||||
.should('have.property', 'name')
|
||||
.and('include', 'Using fixtures to represent data')
|
||||
})
|
||||
cy.wait("@getComment")
|
||||
.its("response.body")
|
||||
.should("have.property", "name")
|
||||
.and("include", "Using fixtures to represent data");
|
||||
});
|
||||
|
||||
it('cy.fixture() or require - load a fixture', function () {
|
||||
// we are inside the "function () { ... }"
|
||||
// callback and can use test context object "this"
|
||||
// "this.example" was loaded in "beforeEach" function callback
|
||||
expect(this.example, 'fixture in the test context')
|
||||
.to.deep.equal(requiredExample)
|
||||
it("cy.fixture() or require - load a fixture", function () {
|
||||
// we are inside the "function () { ... }"
|
||||
// callback and can use test context object "this"
|
||||
// "this.example" was loaded in "beforeEach" function callback
|
||||
expect(this.example, "fixture in the test context").to.deep.equal(requiredExample);
|
||||
|
||||
// or use "cy.wrap" and "should('deep.equal', ...)" assertion
|
||||
cy.wrap(this.example)
|
||||
.should('deep.equal', requiredExample)
|
||||
})
|
||||
// or use "cy.wrap" and "should('deep.equal', ...)" assertion
|
||||
cy.wrap(this.example).should("deep.equal", requiredExample);
|
||||
});
|
||||
|
||||
it('cy.readFile() - read file contents', () => {
|
||||
// https://on.cypress.io/readfile
|
||||
it("cy.readFile() - read file contents", () => {
|
||||
// https://on.cypress.io/readfile
|
||||
|
||||
// You can read a file and yield its contents
|
||||
// The filePath is relative to your project's root.
|
||||
cy.readFile('cypress.json').then((json) => {
|
||||
expect(json).to.be.an('object')
|
||||
})
|
||||
})
|
||||
// You can read a file and yield its contents
|
||||
// The filePath is relative to your project's root.
|
||||
cy.readFile("cypress.json").then((json) => {
|
||||
expect(json).to.be.an("object");
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.writeFile() - write to a file', () => {
|
||||
// https://on.cypress.io/writefile
|
||||
it("cy.writeFile() - write to a file", () => {
|
||||
// https://on.cypress.io/writefile
|
||||
|
||||
// You can write to a file
|
||||
// You can write to a file
|
||||
|
||||
// Use a response from a request to automatically
|
||||
// generate a fixture file for use later
|
||||
cy.request('https://jsonplaceholder.cypress.io/users')
|
||||
.then((response) => {
|
||||
cy.writeFile('cypress/fixtures/users.json', response.body)
|
||||
})
|
||||
// Use a response from a request to automatically
|
||||
// generate a fixture file for use later
|
||||
cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
|
||||
cy.writeFile("cypress/fixtures/users.json", response.body);
|
||||
});
|
||||
|
||||
cy.fixture('users').should((users) => {
|
||||
expect(users[0].name).to.exist
|
||||
})
|
||||
cy.fixture("users").should((users) => {
|
||||
expect(users[0].name).to.exist;
|
||||
});
|
||||
|
||||
// JavaScript arrays and objects are stringified
|
||||
// and formatted into text.
|
||||
cy.writeFile('cypress/fixtures/profile.json', {
|
||||
id: 8739,
|
||||
name: 'Jane',
|
||||
email: 'jane@example.com',
|
||||
})
|
||||
// JavaScript arrays and objects are stringified
|
||||
// and formatted into text.
|
||||
cy.writeFile("cypress/fixtures/profile.json", {
|
||||
id: 8739,
|
||||
name: "Jane",
|
||||
email: "jane@example.com"
|
||||
});
|
||||
|
||||
cy.fixture('profile').should((profile) => {
|
||||
expect(profile.name).to.eq('Jane')
|
||||
})
|
||||
})
|
||||
})
|
||||
cy.fixture("profile").should((profile) => {
|
||||
expect(profile.name).to.eq("Jane");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,52 +1,58 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Local Storage', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/local-storage')
|
||||
})
|
||||
// Although local storage is automatically cleared
|
||||
// in between tests to maintain a clean state
|
||||
// sometimes we need to clear the local storage manually
|
||||
context("Local Storage", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/local-storage");
|
||||
});
|
||||
// Although local storage is automatically cleared
|
||||
// in between tests to maintain a clean state
|
||||
// sometimes we need to clear the local storage manually
|
||||
|
||||
it('cy.clearLocalStorage() - clear all data in local storage', () => {
|
||||
// https://on.cypress.io/clearlocalstorage
|
||||
cy.get('.ls-btn').click().should(() => {
|
||||
expect(localStorage.getItem('prop1')).to.eq('red')
|
||||
expect(localStorage.getItem('prop2')).to.eq('blue')
|
||||
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
it("cy.clearLocalStorage() - clear all data in local storage", () => {
|
||||
// https://on.cypress.io/clearlocalstorage
|
||||
cy.get(".ls-btn")
|
||||
.click()
|
||||
.should(() => {
|
||||
expect(localStorage.getItem("prop1")).to.eq("red");
|
||||
expect(localStorage.getItem("prop2")).to.eq("blue");
|
||||
expect(localStorage.getItem("prop3")).to.eq("magenta");
|
||||
});
|
||||
|
||||
// clearLocalStorage() yields the localStorage object
|
||||
cy.clearLocalStorage().should((ls) => {
|
||||
expect(ls.getItem('prop1')).to.be.null
|
||||
expect(ls.getItem('prop2')).to.be.null
|
||||
expect(ls.getItem('prop3')).to.be.null
|
||||
})
|
||||
// clearLocalStorage() yields the localStorage object
|
||||
cy.clearLocalStorage().should((ls) => {
|
||||
expect(ls.getItem("prop1")).to.be.null;
|
||||
expect(ls.getItem("prop2")).to.be.null;
|
||||
expect(ls.getItem("prop3")).to.be.null;
|
||||
});
|
||||
|
||||
cy.get('.ls-btn').click().should(() => {
|
||||
expect(localStorage.getItem('prop1')).to.eq('red')
|
||||
expect(localStorage.getItem('prop2')).to.eq('blue')
|
||||
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
cy.get(".ls-btn")
|
||||
.click()
|
||||
.should(() => {
|
||||
expect(localStorage.getItem("prop1")).to.eq("red");
|
||||
expect(localStorage.getItem("prop2")).to.eq("blue");
|
||||
expect(localStorage.getItem("prop3")).to.eq("magenta");
|
||||
});
|
||||
|
||||
// Clear key matching string in Local Storage
|
||||
cy.clearLocalStorage('prop1').should((ls) => {
|
||||
expect(ls.getItem('prop1')).to.be.null
|
||||
expect(ls.getItem('prop2')).to.eq('blue')
|
||||
expect(ls.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
// Clear key matching string in Local Storage
|
||||
cy.clearLocalStorage("prop1").should((ls) => {
|
||||
expect(ls.getItem("prop1")).to.be.null;
|
||||
expect(ls.getItem("prop2")).to.eq("blue");
|
||||
expect(ls.getItem("prop3")).to.eq("magenta");
|
||||
});
|
||||
|
||||
cy.get('.ls-btn').click().should(() => {
|
||||
expect(localStorage.getItem('prop1')).to.eq('red')
|
||||
expect(localStorage.getItem('prop2')).to.eq('blue')
|
||||
expect(localStorage.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
cy.get(".ls-btn")
|
||||
.click()
|
||||
.should(() => {
|
||||
expect(localStorage.getItem("prop1")).to.eq("red");
|
||||
expect(localStorage.getItem("prop2")).to.eq("blue");
|
||||
expect(localStorage.getItem("prop3")).to.eq("magenta");
|
||||
});
|
||||
|
||||
// Clear keys matching regex in Local Storage
|
||||
cy.clearLocalStorage(/prop1|2/).should((ls) => {
|
||||
expect(ls.getItem('prop1')).to.be.null
|
||||
expect(ls.getItem('prop2')).to.be.null
|
||||
expect(ls.getItem('prop3')).to.eq('magenta')
|
||||
})
|
||||
})
|
||||
})
|
||||
// Clear keys matching regex in Local Storage
|
||||
cy.clearLocalStorage(/prop1|2/).should((ls) => {
|
||||
expect(ls.getItem("prop1")).to.be.null;
|
||||
expect(ls.getItem("prop2")).to.be.null;
|
||||
expect(ls.getItem("prop3")).to.eq("magenta");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Location', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/location')
|
||||
})
|
||||
context("Location", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/location");
|
||||
});
|
||||
|
||||
it('cy.hash() - get the current URL hash', () => {
|
||||
// https://on.cypress.io/hash
|
||||
cy.hash().should('be.empty')
|
||||
})
|
||||
it("cy.hash() - get the current URL hash", () => {
|
||||
// https://on.cypress.io/hash
|
||||
cy.hash().should("be.empty");
|
||||
});
|
||||
|
||||
it('cy.location() - get window.location', () => {
|
||||
// https://on.cypress.io/location
|
||||
cy.location().should((location) => {
|
||||
expect(location.hash).to.be.empty
|
||||
expect(location.href).to.eq('https://example.cypress.io/commands/location')
|
||||
expect(location.host).to.eq('example.cypress.io')
|
||||
expect(location.hostname).to.eq('example.cypress.io')
|
||||
expect(location.origin).to.eq('https://example.cypress.io')
|
||||
expect(location.pathname).to.eq('/commands/location')
|
||||
expect(location.port).to.eq('')
|
||||
expect(location.protocol).to.eq('https:')
|
||||
expect(location.search).to.be.empty
|
||||
})
|
||||
})
|
||||
it("cy.location() - get window.location", () => {
|
||||
// https://on.cypress.io/location
|
||||
cy.location().should((location) => {
|
||||
expect(location.hash).to.be.empty;
|
||||
expect(location.href).to.eq("https://example.cypress.io/commands/location");
|
||||
expect(location.host).to.eq("example.cypress.io");
|
||||
expect(location.hostname).to.eq("example.cypress.io");
|
||||
expect(location.origin).to.eq("https://example.cypress.io");
|
||||
expect(location.pathname).to.eq("/commands/location");
|
||||
expect(location.port).to.eq("");
|
||||
expect(location.protocol).to.eq("https:");
|
||||
expect(location.search).to.be.empty;
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.url() - get the current URL', () => {
|
||||
// https://on.cypress.io/url
|
||||
cy.url().should('eq', 'https://example.cypress.io/commands/location')
|
||||
})
|
||||
})
|
||||
it("cy.url() - get the current URL", () => {
|
||||
// https://on.cypress.io/url
|
||||
cy.url().should("eq", "https://example.cypress.io/commands/location");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,106 +1,98 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Misc', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/misc')
|
||||
})
|
||||
context("Misc", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/misc");
|
||||
});
|
||||
|
||||
it('.end() - end the command chain', () => {
|
||||
// https://on.cypress.io/end
|
||||
it(".end() - end the command chain", () => {
|
||||
// https://on.cypress.io/end
|
||||
|
||||
// cy.end is useful when you want to end a chain of commands
|
||||
// and force Cypress to re-query from the root element
|
||||
cy.get('.misc-table').within(() => {
|
||||
// ends the current chain and yields null
|
||||
cy.contains('Cheryl').click().end()
|
||||
// cy.end is useful when you want to end a chain of commands
|
||||
// and force Cypress to re-query from the root element
|
||||
cy.get(".misc-table").within(() => {
|
||||
// ends the current chain and yields null
|
||||
cy.contains("Cheryl").click().end();
|
||||
|
||||
// queries the entire table again
|
||||
cy.contains('Charles').click()
|
||||
})
|
||||
})
|
||||
// queries the entire table again
|
||||
cy.contains("Charles").click();
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.exec() - execute a system command', () => {
|
||||
// execute a system command.
|
||||
// so you can take actions necessary for
|
||||
// your test outside the scope of Cypress.
|
||||
// https://on.cypress.io/exec
|
||||
it("cy.exec() - execute a system command", () => {
|
||||
// execute a system command.
|
||||
// so you can take actions necessary for
|
||||
// your test outside the scope of Cypress.
|
||||
// https://on.cypress.io/exec
|
||||
|
||||
// we can use Cypress.platform string to
|
||||
// select appropriate command
|
||||
// https://on.cypress/io/platform
|
||||
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`)
|
||||
// we can use Cypress.platform string to
|
||||
// select appropriate command
|
||||
// https://on.cypress/io/platform
|
||||
cy.log(`Platform ${Cypress.platform} architecture ${Cypress.arch}`);
|
||||
|
||||
// on CircleCI Windows build machines we have a failure to run bash shell
|
||||
// https://github.com/cypress-io/cypress/issues/5169
|
||||
// so skip some of the tests by passing flag "--env circle=true"
|
||||
const isCircleOnWindows = Cypress.platform === 'win32' && Cypress.env('circle')
|
||||
// on CircleCI Windows build machines we have a failure to run bash shell
|
||||
// https://github.com/cypress-io/cypress/issues/5169
|
||||
// so skip some of the tests by passing flag "--env circle=true"
|
||||
const isCircleOnWindows = Cypress.platform === "win32" && Cypress.env("circle");
|
||||
|
||||
if (isCircleOnWindows) {
|
||||
cy.log('Skipping test on CircleCI')
|
||||
if (isCircleOnWindows) {
|
||||
cy.log("Skipping test on CircleCI");
|
||||
|
||||
return
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// cy.exec problem on Shippable CI
|
||||
// https://github.com/cypress-io/cypress/issues/6718
|
||||
const isShippable = Cypress.platform === 'linux' && Cypress.env('shippable')
|
||||
// cy.exec problem on Shippable CI
|
||||
// https://github.com/cypress-io/cypress/issues/6718
|
||||
const isShippable = Cypress.platform === "linux" && Cypress.env("shippable");
|
||||
|
||||
if (isShippable) {
|
||||
cy.log('Skipping test on ShippableCI')
|
||||
if (isShippable) {
|
||||
cy.log("Skipping test on ShippableCI");
|
||||
|
||||
return
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
cy.exec('echo Jane Lane')
|
||||
.its('stdout').should('contain', 'Jane Lane')
|
||||
cy.exec("echo Jane Lane").its("stdout").should("contain", "Jane Lane");
|
||||
|
||||
if (Cypress.platform === 'win32') {
|
||||
cy.exec('print cypress.json')
|
||||
.its('stderr').should('be.empty')
|
||||
} else {
|
||||
cy.exec('cat cypress.json')
|
||||
.its('stderr').should('be.empty')
|
||||
if (Cypress.platform === "win32") {
|
||||
cy.exec("print cypress.json").its("stderr").should("be.empty");
|
||||
} else {
|
||||
cy.exec("cat cypress.json").its("stderr").should("be.empty");
|
||||
|
||||
cy.exec('pwd')
|
||||
.its('code').should('eq', 0)
|
||||
}
|
||||
})
|
||||
cy.exec("pwd").its("code").should("eq", 0);
|
||||
}
|
||||
});
|
||||
|
||||
it('cy.focused() - get the DOM element that has focus', () => {
|
||||
// https://on.cypress.io/focused
|
||||
cy.get('.misc-form').find('#name').click()
|
||||
cy.focused().should('have.id', 'name')
|
||||
it("cy.focused() - get the DOM element that has focus", () => {
|
||||
// https://on.cypress.io/focused
|
||||
cy.get(".misc-form").find("#name").click();
|
||||
cy.focused().should("have.id", "name");
|
||||
|
||||
cy.get('.misc-form').find('#description').click()
|
||||
cy.focused().should('have.id', 'description')
|
||||
})
|
||||
cy.get(".misc-form").find("#description").click();
|
||||
cy.focused().should("have.id", "description");
|
||||
});
|
||||
|
||||
context('Cypress.Screenshot', function () {
|
||||
it('cy.screenshot() - take a screenshot', () => {
|
||||
// https://on.cypress.io/screenshot
|
||||
cy.screenshot('my-image')
|
||||
})
|
||||
context("Cypress.Screenshot", function () {
|
||||
it("cy.screenshot() - take a screenshot", () => {
|
||||
// https://on.cypress.io/screenshot
|
||||
cy.screenshot("my-image");
|
||||
});
|
||||
|
||||
it('Cypress.Screenshot.defaults() - change default config of screenshots', function () {
|
||||
Cypress.Screenshot.defaults({
|
||||
blackout: ['.foo'],
|
||||
capture: 'viewport',
|
||||
clip: {x: 0, y: 0, width: 200, height: 200},
|
||||
scale: false,
|
||||
disableTimersAndAnimations: true,
|
||||
screenshotOnRunFailure: true,
|
||||
onBeforeScreenshot() {
|
||||
},
|
||||
onAfterScreenshot() {
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
it("Cypress.Screenshot.defaults() - change default config of screenshots", function () {
|
||||
Cypress.Screenshot.defaults({
|
||||
blackout: [".foo"],
|
||||
capture: "viewport",
|
||||
clip: { x: 0, y: 0, width: 200, height: 200 },
|
||||
scale: false,
|
||||
disableTimersAndAnimations: true,
|
||||
screenshotOnRunFailure: true,
|
||||
onBeforeScreenshot() {},
|
||||
onAfterScreenshot() {}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.wrap() - wrap an object', () => {
|
||||
// https://on.cypress.io/wrap
|
||||
cy.wrap({foo: 'bar'})
|
||||
.should('have.property', 'foo')
|
||||
.and('include', 'bar')
|
||||
})
|
||||
})
|
||||
it("cy.wrap() - wrap an object", () => {
|
||||
// https://on.cypress.io/wrap
|
||||
cy.wrap({ foo: "bar" }).should("have.property", "foo").and("include", "bar");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,56 +1,56 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Navigation', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io')
|
||||
cy.get('.navbar-nav').contains('Commands').click()
|
||||
cy.get('.dropdown-menu').contains('Navigation').click()
|
||||
})
|
||||
context("Navigation", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io");
|
||||
cy.get(".navbar-nav").contains("Commands").click();
|
||||
cy.get(".dropdown-menu").contains("Navigation").click();
|
||||
});
|
||||
|
||||
it('cy.go() - go back or forward in the browser\'s history', () => {
|
||||
// https://on.cypress.io/go
|
||||
it("cy.go() - go back or forward in the browser's history", () => {
|
||||
// https://on.cypress.io/go
|
||||
|
||||
cy.location('pathname').should('include', 'navigation')
|
||||
cy.location("pathname").should("include", "navigation");
|
||||
|
||||
cy.go('back')
|
||||
cy.location('pathname').should('not.include', 'navigation')
|
||||
cy.go("back");
|
||||
cy.location("pathname").should("not.include", "navigation");
|
||||
|
||||
cy.go('forward')
|
||||
cy.location('pathname').should('include', 'navigation')
|
||||
cy.go("forward");
|
||||
cy.location("pathname").should("include", "navigation");
|
||||
|
||||
// clicking back
|
||||
cy.go(-1)
|
||||
cy.location('pathname').should('not.include', 'navigation')
|
||||
// clicking back
|
||||
cy.go(-1);
|
||||
cy.location("pathname").should("not.include", "navigation");
|
||||
|
||||
// clicking forward
|
||||
cy.go(1)
|
||||
cy.location('pathname').should('include', 'navigation')
|
||||
})
|
||||
// clicking forward
|
||||
cy.go(1);
|
||||
cy.location("pathname").should("include", "navigation");
|
||||
});
|
||||
|
||||
it('cy.reload() - reload the page', () => {
|
||||
// https://on.cypress.io/reload
|
||||
cy.reload()
|
||||
it("cy.reload() - reload the page", () => {
|
||||
// https://on.cypress.io/reload
|
||||
cy.reload();
|
||||
|
||||
// reload the page without using the cache
|
||||
cy.reload(true)
|
||||
})
|
||||
// reload the page without using the cache
|
||||
cy.reload(true);
|
||||
});
|
||||
|
||||
it('cy.visit() - visit a remote url', () => {
|
||||
// https://on.cypress.io/visit
|
||||
it("cy.visit() - visit a remote url", () => {
|
||||
// https://on.cypress.io/visit
|
||||
|
||||
// Visit any sub-domain of your current domain
|
||||
// Visit any sub-domain of your current domain
|
||||
|
||||
// Pass options to the visit
|
||||
cy.visit('https://example.cypress.io/commands/navigation', {
|
||||
timeout: 50000, // increase total time for the visit to resolve
|
||||
onBeforeLoad(contentWindow) {
|
||||
// contentWindow is the remote page's window object
|
||||
expect(typeof contentWindow === 'object').to.be.true
|
||||
},
|
||||
onLoad(contentWindow) {
|
||||
// contentWindow is the remote page's window object
|
||||
expect(typeof contentWindow === 'object').to.be.true
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
// Pass options to the visit
|
||||
cy.visit("https://example.cypress.io/commands/navigation", {
|
||||
timeout: 50000, // increase total time for the visit to resolve
|
||||
onBeforeLoad(contentWindow) {
|
||||
// contentWindow is the remote page's window object
|
||||
expect(typeof contentWindow === "object").to.be.true;
|
||||
},
|
||||
onLoad(contentWindow) {
|
||||
// contentWindow is the remote page's window object
|
||||
expect(typeof contentWindow === "object").to.be.true;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,163 +1,165 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Network Requests', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/network-requests')
|
||||
context("Network Requests", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/network-requests");
|
||||
});
|
||||
|
||||
// Manage HTTP requests in your app
|
||||
|
||||
it("cy.request() - make an XHR request", () => {
|
||||
// https://on.cypress.io/request
|
||||
cy.request("https://jsonplaceholder.cypress.io/comments").should((response) => {
|
||||
expect(response.status).to.eq(200);
|
||||
// the server sometimes gets an extra comment posted from another machine
|
||||
// which gets returned as 1 extra object
|
||||
expect(response.body).to.have.property("length").and.be.oneOf([500, 501]);
|
||||
expect(response).to.have.property("headers");
|
||||
expect(response).to.have.property("duration");
|
||||
});
|
||||
});
|
||||
|
||||
it("cy.request() - verify response using BDD syntax", () => {
|
||||
cy.request("https://jsonplaceholder.cypress.io/comments").then((response) => {
|
||||
// https://on.cypress.io/assertions
|
||||
expect(response).property("status").to.equal(200);
|
||||
expect(response).property("body").to.have.property("length").and.be.oneOf([500, 501]);
|
||||
expect(response).to.include.keys("headers", "duration");
|
||||
});
|
||||
});
|
||||
|
||||
it("cy.request() with query parameters", () => {
|
||||
// will execute request
|
||||
// https://jsonplaceholder.cypress.io/comments?postId=1&id=3
|
||||
cy.request({
|
||||
url: "https://jsonplaceholder.cypress.io/comments",
|
||||
qs: {
|
||||
postId: 1,
|
||||
id: 3
|
||||
}
|
||||
})
|
||||
.its("body")
|
||||
.should("be.an", "array")
|
||||
.and("have.length", 1)
|
||||
.its("0") // yields first element of the array
|
||||
.should("contain", {
|
||||
postId: 1,
|
||||
id: 3
|
||||
});
|
||||
});
|
||||
|
||||
// Manage HTTP requests in your app
|
||||
it("cy.request() - pass result to the second request", () => {
|
||||
// first, let's find out the userId of the first user we have
|
||||
cy.request("https://jsonplaceholder.cypress.io/users?_limit=1")
|
||||
.its("body") // yields the response object
|
||||
.its("0") // yields the first element of the returned list
|
||||
// the above two commands its('body').its('0')
|
||||
// can be written as its('body.0')
|
||||
// if you do not care about TypeScript checks
|
||||
.then((user) => {
|
||||
expect(user).property("id").to.be.a("number");
|
||||
// make a new post on behalf of the user
|
||||
cy.request("POST", "https://jsonplaceholder.cypress.io/posts", {
|
||||
userId: user.id,
|
||||
title: "Cypress Test Runner",
|
||||
body: "Fast, easy and reliable testing for anything that runs in a browser."
|
||||
});
|
||||
})
|
||||
// note that the value here is the returned value of the 2nd request
|
||||
// which is the new post object
|
||||
.then((response) => {
|
||||
expect(response).property("status").to.equal(201); // new entity created
|
||||
expect(response).property("body").to.contain({
|
||||
title: "Cypress Test Runner"
|
||||
});
|
||||
|
||||
it('cy.request() - make an XHR request', () => {
|
||||
// https://on.cypress.io/request
|
||||
cy.request('https://jsonplaceholder.cypress.io/comments')
|
||||
.should((response) => {
|
||||
expect(response.status).to.eq(200)
|
||||
// the server sometimes gets an extra comment posted from another machine
|
||||
// which gets returned as 1 extra object
|
||||
expect(response.body).to.have.property('length').and.be.oneOf([500, 501])
|
||||
expect(response).to.have.property('headers')
|
||||
expect(response).to.have.property('duration')
|
||||
})
|
||||
})
|
||||
// we don't know the exact post id - only that it will be > 100
|
||||
// since JSONPlaceholder has built-in 100 posts
|
||||
expect(response.body).property("id").to.be.a("number").and.to.be.gt(100);
|
||||
|
||||
it('cy.request() - verify response using BDD syntax', () => {
|
||||
cy.request('https://jsonplaceholder.cypress.io/comments')
|
||||
.then((response) => {
|
||||
// https://on.cypress.io/assertions
|
||||
expect(response).property('status').to.equal(200)
|
||||
expect(response).property('body').to.have.property('length').and.be.oneOf([500, 501])
|
||||
expect(response).to.include.keys('headers', 'duration')
|
||||
})
|
||||
})
|
||||
// we don't know the user id here - since it was in above closure
|
||||
// so in this test just confirm that the property is there
|
||||
expect(response.body).property("userId").to.be.a("number");
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.request() with query parameters', () => {
|
||||
// will execute request
|
||||
// https://jsonplaceholder.cypress.io/comments?postId=1&id=3
|
||||
cy.request({
|
||||
url: 'https://jsonplaceholder.cypress.io/comments',
|
||||
qs: {
|
||||
postId: 1,
|
||||
id: 3,
|
||||
},
|
||||
it("cy.request() - save response in the shared test context", () => {
|
||||
// https://on.cypress.io/variables-and-aliases
|
||||
cy.request("https://jsonplaceholder.cypress.io/users?_limit=1")
|
||||
.its("body")
|
||||
.its("0") // yields the first element of the returned list
|
||||
.as("user") // saves the object in the test context
|
||||
.then(function () {
|
||||
// NOTE 👀
|
||||
// By the time this callback runs the "as('user')" command
|
||||
// has saved the user object in the test context.
|
||||
// To access the test context we need to use
|
||||
// the "function () { ... }" callback form,
|
||||
// otherwise "this" points at a wrong or undefined object!
|
||||
cy.request("POST", "https://jsonplaceholder.cypress.io/posts", {
|
||||
userId: this.user.id,
|
||||
title: "Cypress Test Runner",
|
||||
body: "Fast, easy and reliable testing for anything that runs in a browser."
|
||||
})
|
||||
.its('body')
|
||||
.should('be.an', 'array')
|
||||
.and('have.length', 1)
|
||||
.its('0') // yields first element of the array
|
||||
.should('contain', {
|
||||
postId: 1,
|
||||
id: 3,
|
||||
})
|
||||
})
|
||||
.its("body")
|
||||
.as("post"); // save the new post from the response
|
||||
})
|
||||
.then(function () {
|
||||
// When this callback runs, both "cy.request" API commands have finished
|
||||
// and the test context has "user" and "post" objects set.
|
||||
// Let's verify them.
|
||||
expect(this.post, "post has the right user id").property("userId").to.equal(this.user.id);
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.request() - pass result to the second request', () => {
|
||||
// first, let's find out the userId of the first user we have
|
||||
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
|
||||
.its('body') // yields the response object
|
||||
.its('0') // yields the first element of the returned list
|
||||
// the above two commands its('body').its('0')
|
||||
// can be written as its('body.0')
|
||||
// if you do not care about TypeScript checks
|
||||
.then((user) => {
|
||||
expect(user).property('id').to.be.a('number')
|
||||
// make a new post on behalf of the user
|
||||
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
|
||||
userId: user.id,
|
||||
title: 'Cypress Test Runner',
|
||||
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
|
||||
})
|
||||
})
|
||||
// note that the value here is the returned value of the 2nd request
|
||||
// which is the new post object
|
||||
.then((response) => {
|
||||
expect(response).property('status').to.equal(201) // new entity created
|
||||
expect(response).property('body').to.contain({
|
||||
title: 'Cypress Test Runner',
|
||||
})
|
||||
it("cy.intercept() - route responses to matching requests", () => {
|
||||
// https://on.cypress.io/intercept
|
||||
|
||||
// we don't know the exact post id - only that it will be > 100
|
||||
// since JSONPlaceholder has built-in 100 posts
|
||||
expect(response.body).property('id').to.be.a('number')
|
||||
.and.to.be.gt(100)
|
||||
let message = "whoa, this comment does not exist";
|
||||
|
||||
// we don't know the user id here - since it was in above closure
|
||||
// so in this test just confirm that the property is there
|
||||
expect(response.body).property('userId').to.be.a('number')
|
||||
})
|
||||
})
|
||||
// Listen to GET to comments/1
|
||||
cy.intercept("GET", "**/comments/*").as("getComment");
|
||||
|
||||
it('cy.request() - save response in the shared test context', () => {
|
||||
// https://on.cypress.io/variables-and-aliases
|
||||
cy.request('https://jsonplaceholder.cypress.io/users?_limit=1')
|
||||
.its('body').its('0') // yields the first element of the returned list
|
||||
.as('user') // saves the object in the test context
|
||||
.then(function () {
|
||||
// NOTE 👀
|
||||
// By the time this callback runs the "as('user')" command
|
||||
// has saved the user object in the test context.
|
||||
// To access the test context we need to use
|
||||
// the "function () { ... }" callback form,
|
||||
// otherwise "this" points at a wrong or undefined object!
|
||||
cy.request('POST', 'https://jsonplaceholder.cypress.io/posts', {
|
||||
userId: this.user.id,
|
||||
title: 'Cypress Test Runner',
|
||||
body: 'Fast, easy and reliable testing for anything that runs in a browser.',
|
||||
})
|
||||
.its('body').as('post') // save the new post from the response
|
||||
})
|
||||
.then(function () {
|
||||
// When this callback runs, both "cy.request" API commands have finished
|
||||
// and the test context has "user" and "post" objects set.
|
||||
// Let's verify them.
|
||||
expect(this.post, 'post has the right user id').property('userId').to.equal(this.user.id)
|
||||
})
|
||||
})
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get(".network-btn").click();
|
||||
|
||||
it('cy.intercept() - route responses to matching requests', () => {
|
||||
// https://on.cypress.io/intercept
|
||||
// https://on.cypress.io/wait
|
||||
cy.wait("@getComment").its("response.statusCode").should("be.oneOf", [200, 304]);
|
||||
|
||||
let message = 'whoa, this comment does not exist'
|
||||
// Listen to POST to comments
|
||||
cy.intercept("POST", "**/comments").as("postComment");
|
||||
|
||||
// Listen to GET to comments/1
|
||||
cy.intercept('GET', '**/comments/*').as('getComment')
|
||||
// we have code that posts a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get(".network-post").click();
|
||||
cy.wait("@postComment").should(({ request, response }) => {
|
||||
expect(request.body).to.include("email");
|
||||
expect(request.headers).to.have.property("content-type");
|
||||
expect(response && response.body).to.have.property("name", "Using POST in cy.intercept()");
|
||||
});
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-btn').click()
|
||||
// Stub a response to PUT comments/ ****
|
||||
cy.intercept(
|
||||
{
|
||||
method: "PUT",
|
||||
url: "**/comments/*"
|
||||
},
|
||||
{
|
||||
statusCode: 404,
|
||||
body: { error: message },
|
||||
headers: { "access-control-allow-origin": "*" },
|
||||
delayMs: 500
|
||||
}
|
||||
).as("putComment");
|
||||
|
||||
// https://on.cypress.io/wait
|
||||
cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
// we have code that puts a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get(".network-put").click();
|
||||
|
||||
// Listen to POST to comments
|
||||
cy.intercept('POST', '**/comments').as('postComment')
|
||||
cy.wait("@putComment");
|
||||
|
||||
// we have code that posts a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-post').click()
|
||||
cy.wait('@postComment').should(({request, response}) => {
|
||||
expect(request.body).to.include('email')
|
||||
expect(request.headers).to.have.property('content-type')
|
||||
expect(response && response.body).to.have.property('name', 'Using POST in cy.intercept()')
|
||||
})
|
||||
|
||||
// Stub a response to PUT comments/ ****
|
||||
cy.intercept({
|
||||
method: 'PUT',
|
||||
url: '**/comments/*',
|
||||
}, {
|
||||
statusCode: 404,
|
||||
body: {error: message},
|
||||
headers: {'access-control-allow-origin': '*'},
|
||||
delayMs: 500,
|
||||
}).as('putComment')
|
||||
|
||||
// we have code that puts a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-put').click()
|
||||
|
||||
cy.wait('@putComment')
|
||||
|
||||
// our 404 statusCode logic in scripts.js executed
|
||||
cy.get('.network-put-comment').should('contain', message)
|
||||
})
|
||||
})
|
||||
// our 404 statusCode logic in scripts.js executed
|
||||
cy.get(".network-put-comment").should("contain", message);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,114 +1,100 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Querying', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/querying')
|
||||
})
|
||||
context("Querying", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/querying");
|
||||
});
|
||||
|
||||
// The most commonly used query is 'cy.get()', you can
|
||||
// think of this like the '$' in jQuery
|
||||
// The most commonly used query is 'cy.get()', you can
|
||||
// think of this like the '$' in jQuery
|
||||
|
||||
it('cy.get() - query DOM elements', () => {
|
||||
// https://on.cypress.io/get
|
||||
it("cy.get() - query DOM elements", () => {
|
||||
// https://on.cypress.io/get
|
||||
|
||||
cy.get('#query-btn').should('contain', 'Button')
|
||||
cy.get("#query-btn").should("contain", "Button");
|
||||
|
||||
cy.get('.query-btn').should('contain', 'Button')
|
||||
cy.get(".query-btn").should("contain", "Button");
|
||||
|
||||
cy.get('#querying .well>button:first').should('contain', 'Button')
|
||||
// ↲
|
||||
// Use CSS selectors just like jQuery
|
||||
cy.get("#querying .well>button:first").should("contain", "Button");
|
||||
// ↲
|
||||
// Use CSS selectors just like jQuery
|
||||
|
||||
cy.get('[data-test-id="test-example"]').should('have.class', 'example')
|
||||
cy.get('[data-test-id="test-example"]').should("have.class", "example");
|
||||
|
||||
// 'cy.get()' yields jQuery object, you can get its attribute
|
||||
// by invoking `.attr()` method
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.invoke('attr', 'data-test-id')
|
||||
.should('equal', 'test-example')
|
||||
// 'cy.get()' yields jQuery object, you can get its attribute
|
||||
// by invoking `.attr()` method
|
||||
cy.get('[data-test-id="test-example"]').invoke("attr", "data-test-id").should("equal", "test-example");
|
||||
|
||||
// or you can get element's CSS property
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.invoke('css', 'position')
|
||||
.should('equal', 'static')
|
||||
// or you can get element's CSS property
|
||||
cy.get('[data-test-id="test-example"]').invoke("css", "position").should("equal", "static");
|
||||
|
||||
// or use assertions directly during 'cy.get()'
|
||||
// https://on.cypress.io/assertions
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.should('have.attr', 'data-test-id', 'test-example')
|
||||
.and('have.css', 'position', 'static')
|
||||
})
|
||||
// or use assertions directly during 'cy.get()'
|
||||
// https://on.cypress.io/assertions
|
||||
cy.get('[data-test-id="test-example"]')
|
||||
.should("have.attr", "data-test-id", "test-example")
|
||||
.and("have.css", "position", "static");
|
||||
});
|
||||
|
||||
it('cy.contains() - query DOM elements with matching content', () => {
|
||||
// https://on.cypress.io/contains
|
||||
cy.get('.query-list')
|
||||
.contains('bananas')
|
||||
.should('have.class', 'third')
|
||||
it("cy.contains() - query DOM elements with matching content", () => {
|
||||
// https://on.cypress.io/contains
|
||||
cy.get(".query-list").contains("bananas").should("have.class", "third");
|
||||
|
||||
// we can pass a regexp to `.contains()`
|
||||
cy.get('.query-list')
|
||||
.contains(/^b\w+/)
|
||||
.should('have.class', 'third')
|
||||
// we can pass a regexp to `.contains()`
|
||||
cy.get(".query-list").contains(/^b\w+/).should("have.class", "third");
|
||||
|
||||
cy.get('.query-list')
|
||||
.contains('apples')
|
||||
.should('have.class', 'first')
|
||||
cy.get(".query-list").contains("apples").should("have.class", "first");
|
||||
|
||||
// passing a selector to contains will
|
||||
// yield the selector containing the text
|
||||
cy.get('#querying')
|
||||
.contains('ul', 'oranges')
|
||||
.should('have.class', 'query-list')
|
||||
// passing a selector to contains will
|
||||
// yield the selector containing the text
|
||||
cy.get("#querying").contains("ul", "oranges").should("have.class", "query-list");
|
||||
|
||||
cy.get('.query-button')
|
||||
.contains('Save Form')
|
||||
.should('have.class', 'btn')
|
||||
})
|
||||
cy.get(".query-button").contains("Save Form").should("have.class", "btn");
|
||||
});
|
||||
|
||||
it('.within() - query DOM elements within a specific element', () => {
|
||||
// https://on.cypress.io/within
|
||||
cy.get('.query-form').within(() => {
|
||||
cy.get('input:first').should('have.attr', 'placeholder', 'Email')
|
||||
cy.get('input:last').should('have.attr', 'placeholder', 'Password')
|
||||
})
|
||||
})
|
||||
it(".within() - query DOM elements within a specific element", () => {
|
||||
// https://on.cypress.io/within
|
||||
cy.get(".query-form").within(() => {
|
||||
cy.get("input:first").should("have.attr", "placeholder", "Email");
|
||||
cy.get("input:last").should("have.attr", "placeholder", "Password");
|
||||
});
|
||||
});
|
||||
|
||||
it('cy.root() - query the root DOM element', () => {
|
||||
// https://on.cypress.io/root
|
||||
it("cy.root() - query the root DOM element", () => {
|
||||
// https://on.cypress.io/root
|
||||
|
||||
// By default, root is the document
|
||||
cy.root().should('match', 'html')
|
||||
// By default, root is the document
|
||||
cy.root().should("match", "html");
|
||||
|
||||
cy.get('.query-ul').within(() => {
|
||||
// In this within, the root is now the ul DOM element
|
||||
cy.root().should('have.class', 'query-ul')
|
||||
})
|
||||
})
|
||||
cy.get(".query-ul").within(() => {
|
||||
// In this within, the root is now the ul DOM element
|
||||
cy.root().should("have.class", "query-ul");
|
||||
});
|
||||
});
|
||||
|
||||
it('best practices - selecting elements', () => {
|
||||
// https://on.cypress.io/best-practices#Selecting-Elements
|
||||
cy.get('[data-cy=best-practices-selecting-elements]').within(() => {
|
||||
// Worst - too generic, no context
|
||||
cy.get('button').click()
|
||||
it("best practices - selecting elements", () => {
|
||||
// https://on.cypress.io/best-practices#Selecting-Elements
|
||||
cy.get("[data-cy=best-practices-selecting-elements]").within(() => {
|
||||
// Worst - too generic, no context
|
||||
cy.get("button").click();
|
||||
|
||||
// Bad. Coupled to styling. Highly subject to change.
|
||||
cy.get('.btn.btn-large').click()
|
||||
// Bad. Coupled to styling. Highly subject to change.
|
||||
cy.get(".btn.btn-large").click();
|
||||
|
||||
// Average. Coupled to the `name` attribute which has HTML semantics.
|
||||
cy.get('[name=submission]').click()
|
||||
// Average. Coupled to the `name` attribute which has HTML semantics.
|
||||
cy.get("[name=submission]").click();
|
||||
|
||||
// Better. But still coupled to styling or JS event listeners.
|
||||
cy.get('#main').click()
|
||||
// Better. But still coupled to styling or JS event listeners.
|
||||
cy.get("#main").click();
|
||||
|
||||
// Slightly better. Uses an ID but also ensures the element
|
||||
// has an ARIA role attribute
|
||||
cy.get('#main[role=button]').click()
|
||||
// Slightly better. Uses an ID but also ensures the element
|
||||
// has an ARIA role attribute
|
||||
cy.get("#main[role=button]").click();
|
||||
|
||||
// Much better. But still coupled to text content that may change.
|
||||
cy.contains('Submit').click()
|
||||
// Much better. But still coupled to text content that may change.
|
||||
cy.contains("Submit").click();
|
||||
|
||||
// Best. Insulated from all changes.
|
||||
cy.get('[data-cy=submit]').click()
|
||||
})
|
||||
})
|
||||
})
|
||||
// Best. Insulated from all changes.
|
||||
cy.get("[data-cy=submit]").click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,205 +2,202 @@
|
||||
// remove no check once Cypress.sinon is typed
|
||||
// https://github.com/cypress-io/cypress/issues/6720
|
||||
|
||||
context('Spies, Stubs, and Clock', () => {
|
||||
it('cy.spy() - wrap a method in a spy', () => {
|
||||
// https://on.cypress.io/spy
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
context("Spies, Stubs, and Clock", () => {
|
||||
it("cy.spy() - wrap a method in a spy", () => {
|
||||
// https://on.cypress.io/spy
|
||||
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
||||
|
||||
const obj = {
|
||||
foo() {
|
||||
},
|
||||
}
|
||||
const obj = {
|
||||
foo() {}
|
||||
};
|
||||
|
||||
const spy = cy.spy(obj, 'foo').as('anyArgs')
|
||||
const spy = cy.spy(obj, "foo").as("anyArgs");
|
||||
|
||||
obj.foo()
|
||||
obj.foo();
|
||||
|
||||
expect(spy).to.be.called
|
||||
})
|
||||
expect(spy).to.be.called;
|
||||
});
|
||||
|
||||
it('cy.spy() retries until assertions pass', () => {
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
it("cy.spy() retries until assertions pass", () => {
|
||||
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
||||
|
||||
const obj = {
|
||||
/**
|
||||
* Prints the argument passed
|
||||
* @param x {any}
|
||||
*/
|
||||
foo(x) {
|
||||
console.log('obj.foo called with', x)
|
||||
},
|
||||
}
|
||||
const obj = {
|
||||
/**
|
||||
* Prints the argument passed
|
||||
* @param x {any}
|
||||
*/
|
||||
foo(x) {
|
||||
console.log("obj.foo called with", x);
|
||||
}
|
||||
};
|
||||
|
||||
cy.spy(obj, 'foo').as('foo')
|
||||
cy.spy(obj, "foo").as("foo");
|
||||
|
||||
setTimeout(() => {
|
||||
obj.foo('first')
|
||||
}, 500)
|
||||
setTimeout(() => {
|
||||
obj.foo("first");
|
||||
}, 500);
|
||||
|
||||
setTimeout(() => {
|
||||
obj.foo('second')
|
||||
}, 2500)
|
||||
setTimeout(() => {
|
||||
obj.foo("second");
|
||||
}, 2500);
|
||||
|
||||
cy.get('@foo').should('have.been.calledTwice')
|
||||
})
|
||||
cy.get("@foo").should("have.been.calledTwice");
|
||||
});
|
||||
|
||||
it('cy.stub() - create a stub and/or replace a function with stub', () => {
|
||||
// https://on.cypress.io/stub
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
it("cy.stub() - create a stub and/or replace a function with stub", () => {
|
||||
// https://on.cypress.io/stub
|
||||
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
||||
|
||||
const obj = {
|
||||
/**
|
||||
* prints both arguments to the console
|
||||
* @param a {string}
|
||||
* @param b {string}
|
||||
*/
|
||||
foo(a, b) {
|
||||
console.log('a', a, 'b', b)
|
||||
},
|
||||
}
|
||||
const obj = {
|
||||
/**
|
||||
* prints both arguments to the console
|
||||
* @param a {string}
|
||||
* @param b {string}
|
||||
*/
|
||||
foo(a, b) {
|
||||
console.log("a", a, "b", b);
|
||||
}
|
||||
};
|
||||
|
||||
const stub = cy.stub(obj, 'foo').as('foo')
|
||||
const stub = cy.stub(obj, "foo").as("foo");
|
||||
|
||||
obj.foo('foo', 'bar')
|
||||
obj.foo("foo", "bar");
|
||||
|
||||
expect(stub).to.be.called
|
||||
})
|
||||
expect(stub).to.be.called;
|
||||
});
|
||||
|
||||
it('cy.clock() - control time in the browser', () => {
|
||||
// https://on.cypress.io/clock
|
||||
it("cy.clock() - control time in the browser", () => {
|
||||
// https://on.cypress.io/clock
|
||||
|
||||
// create the date in UTC so its always the same
|
||||
// no matter what local timezone the browser is running in
|
||||
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
|
||||
// create the date in UTC so its always the same
|
||||
// no matter what local timezone the browser is running in
|
||||
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
|
||||
|
||||
cy.clock(now)
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
cy.get('#clock-div').click()
|
||||
.should('have.text', '1489449600')
|
||||
})
|
||||
cy.clock(now);
|
||||
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
||||
cy.get("#clock-div").click().should("have.text", "1489449600");
|
||||
});
|
||||
|
||||
it('cy.tick() - move time in the browser', () => {
|
||||
// https://on.cypress.io/tick
|
||||
it("cy.tick() - move time in the browser", () => {
|
||||
// https://on.cypress.io/tick
|
||||
|
||||
// create the date in UTC so its always the same
|
||||
// no matter what local timezone the browser is running in
|
||||
const now = new Date(Date.UTC(2017, 2, 14)).getTime()
|
||||
// create the date in UTC so its always the same
|
||||
// no matter what local timezone the browser is running in
|
||||
const now = new Date(Date.UTC(2017, 2, 14)).getTime();
|
||||
|
||||
cy.clock(now)
|
||||
cy.visit('https://example.cypress.io/commands/spies-stubs-clocks')
|
||||
cy.get('#tick-div').click()
|
||||
.should('have.text', '1489449600')
|
||||
cy.clock(now);
|
||||
cy.visit("https://example.cypress.io/commands/spies-stubs-clocks");
|
||||
cy.get("#tick-div").click().should("have.text", "1489449600");
|
||||
|
||||
cy.tick(10000) // 10 seconds passed
|
||||
cy.get('#tick-div').click()
|
||||
.should('have.text', '1489449610')
|
||||
})
|
||||
cy.tick(10000); // 10 seconds passed
|
||||
cy.get("#tick-div").click().should("have.text", "1489449610");
|
||||
});
|
||||
|
||||
it('cy.stub() matches depending on arguments', () => {
|
||||
// see all possible matchers at
|
||||
// https://sinonjs.org/releases/latest/matchers/
|
||||
const greeter = {
|
||||
/**
|
||||
* Greets a person
|
||||
* @param {string} name
|
||||
*/
|
||||
greet(name) {
|
||||
return `Hello, ${name}!`
|
||||
},
|
||||
}
|
||||
it("cy.stub() matches depending on arguments", () => {
|
||||
// see all possible matchers at
|
||||
// https://sinonjs.org/releases/latest/matchers/
|
||||
const greeter = {
|
||||
/**
|
||||
* Greets a person
|
||||
* @param {string} name
|
||||
*/
|
||||
greet(name) {
|
||||
return `Hello, ${name}!`;
|
||||
}
|
||||
};
|
||||
|
||||
cy.stub(greeter, 'greet')
|
||||
.callThrough() // if you want non-matched calls to call the real method
|
||||
.withArgs(Cypress.sinon.match.string).returns('Hi')
|
||||
.withArgs(Cypress.sinon.match.number).throws(new Error('Invalid name'))
|
||||
cy.stub(greeter, "greet")
|
||||
.callThrough() // if you want non-matched calls to call the real method
|
||||
.withArgs(Cypress.sinon.match.string)
|
||||
.returns("Hi")
|
||||
.withArgs(Cypress.sinon.match.number)
|
||||
.throws(new Error("Invalid name"));
|
||||
|
||||
expect(greeter.greet('World')).to.equal('Hi')
|
||||
// @ts-ignore
|
||||
expect(() => greeter.greet(42)).to.throw('Invalid name')
|
||||
expect(greeter.greet).to.have.been.calledTwice
|
||||
expect(greeter.greet("World")).to.equal("Hi");
|
||||
// @ts-ignore
|
||||
expect(() => greeter.greet(42)).to.throw("Invalid name");
|
||||
expect(greeter.greet).to.have.been.calledTwice;
|
||||
|
||||
// non-matched calls goes the actual method
|
||||
// @ts-ignore
|
||||
expect(greeter.greet()).to.equal('Hello, undefined!')
|
||||
})
|
||||
// non-matched calls goes the actual method
|
||||
// @ts-ignore
|
||||
expect(greeter.greet()).to.equal("Hello, undefined!");
|
||||
});
|
||||
|
||||
it('matches call arguments using Sinon matchers', () => {
|
||||
// see all possible matchers at
|
||||
// https://sinonjs.org/releases/latest/matchers/
|
||||
const calculator = {
|
||||
/**
|
||||
* returns the sum of two arguments
|
||||
* @param a {number}
|
||||
* @param b {number}
|
||||
*/
|
||||
add(a, b) {
|
||||
return a + b
|
||||
},
|
||||
}
|
||||
it("matches call arguments using Sinon matchers", () => {
|
||||
// see all possible matchers at
|
||||
// https://sinonjs.org/releases/latest/matchers/
|
||||
const calculator = {
|
||||
/**
|
||||
* returns the sum of two arguments
|
||||
* @param a {number}
|
||||
* @param b {number}
|
||||
*/
|
||||
add(a, b) {
|
||||
return a + b;
|
||||
}
|
||||
};
|
||||
|
||||
const spy = cy.spy(calculator, 'add').as('add')
|
||||
const spy = cy.spy(calculator, "add").as("add");
|
||||
|
||||
expect(calculator.add(2, 3)).to.equal(5)
|
||||
expect(calculator.add(2, 3)).to.equal(5);
|
||||
|
||||
// if we want to assert the exact values used during the call
|
||||
expect(spy).to.be.calledWith(2, 3)
|
||||
// if we want to assert the exact values used during the call
|
||||
expect(spy).to.be.calledWith(2, 3);
|
||||
|
||||
// let's confirm "add" method was called with two numbers
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.number, Cypress.sinon.match.number)
|
||||
// let's confirm "add" method was called with two numbers
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.number, Cypress.sinon.match.number);
|
||||
|
||||
// alternatively, provide the value to match
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match(2), Cypress.sinon.match(3))
|
||||
// alternatively, provide the value to match
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match(2), Cypress.sinon.match(3));
|
||||
|
||||
// match any value
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3)
|
||||
// match any value
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.any, 3);
|
||||
|
||||
// match any value from a list
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3)
|
||||
// match any value from a list
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match.in([1, 2, 3]), 3);
|
||||
|
||||
/**
|
||||
* Returns true if the given number is event
|
||||
* @param {number} x
|
||||
*/
|
||||
const isEven = (x) => x % 2 === 0
|
||||
/**
|
||||
* Returns true if the given number is event
|
||||
* @param {number} x
|
||||
*/
|
||||
const isEven = (x) => x % 2 === 0;
|
||||
|
||||
// expect the value to pass a custom predicate function
|
||||
// the second argument to "sinon.match(predicate, message)" is
|
||||
// shown if the predicate does not pass and assertion fails
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, 'isEven'), 3)
|
||||
// expect the value to pass a custom predicate function
|
||||
// the second argument to "sinon.match(predicate, message)" is
|
||||
// shown if the predicate does not pass and assertion fails
|
||||
expect(spy).to.be.calledWith(Cypress.sinon.match(isEven, "isEven"), 3);
|
||||
|
||||
/**
|
||||
* Returns a function that checks if a given number is larger than the limit
|
||||
* @param {number} limit
|
||||
* @returns {(x: number) => boolean}
|
||||
*/
|
||||
const isGreaterThan = (limit) => (x) => x > limit
|
||||
/**
|
||||
* Returns a function that checks if a given number is larger than the limit
|
||||
* @param {number} limit
|
||||
* @returns {(x: number) => boolean}
|
||||
*/
|
||||
const isGreaterThan = (limit) => (x) => x > limit;
|
||||
|
||||
/**
|
||||
* Returns a function that checks if a given number is less than the limit
|
||||
* @param {number} limit
|
||||
* @returns {(x: number) => boolean}
|
||||
*/
|
||||
const isLessThan = (limit) => (x) => x < limit
|
||||
/**
|
||||
* Returns a function that checks if a given number is less than the limit
|
||||
* @param {number} limit
|
||||
* @returns {(x: number) => boolean}
|
||||
*/
|
||||
const isLessThan = (limit) => (x) => x < limit;
|
||||
|
||||
// you can combine several matchers using "and", "or"
|
||||
expect(spy).to.be.calledWith(
|
||||
Cypress.sinon.match.number,
|
||||
Cypress.sinon.match(isGreaterThan(2), '> 2').and(Cypress.sinon.match(isLessThan(4), '< 4')),
|
||||
)
|
||||
// you can combine several matchers using "and", "or"
|
||||
expect(spy).to.be.calledWith(
|
||||
Cypress.sinon.match.number,
|
||||
Cypress.sinon.match(isGreaterThan(2), "> 2").and(Cypress.sinon.match(isLessThan(4), "< 4"))
|
||||
);
|
||||
|
||||
expect(spy).to.be.calledWith(
|
||||
Cypress.sinon.match.number,
|
||||
Cypress.sinon.match(isGreaterThan(200), '> 200').or(Cypress.sinon.match(3)),
|
||||
)
|
||||
expect(spy).to.be.calledWith(
|
||||
Cypress.sinon.match.number,
|
||||
Cypress.sinon.match(isGreaterThan(200), "> 200").or(Cypress.sinon.match(3))
|
||||
);
|
||||
|
||||
// matchers can be used from BDD assertions
|
||||
cy.get('@add').should('have.been.calledWith',
|
||||
Cypress.sinon.match.number, Cypress.sinon.match(3))
|
||||
// matchers can be used from BDD assertions
|
||||
cy.get("@add").should("have.been.calledWith", Cypress.sinon.match.number, Cypress.sinon.match(3));
|
||||
|
||||
// you can alias matchers for shorter test code
|
||||
const {match: M} = Cypress.sinon
|
||||
// you can alias matchers for shorter test code
|
||||
const { match: M } = Cypress.sinon;
|
||||
|
||||
cy.get('@add').should('have.been.calledWith', M.number, M(3))
|
||||
})
|
||||
})
|
||||
cy.get("@add").should("have.been.calledWith", M.number, M(3));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,121 +1,97 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Traversal', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/traversal')
|
||||
})
|
||||
context("Traversal", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/traversal");
|
||||
});
|
||||
|
||||
it('.children() - get child DOM elements', () => {
|
||||
// https://on.cypress.io/children
|
||||
cy.get('.traversal-breadcrumb')
|
||||
.children('.active')
|
||||
.should('contain', 'Data')
|
||||
})
|
||||
it(".children() - get child DOM elements", () => {
|
||||
// https://on.cypress.io/children
|
||||
cy.get(".traversal-breadcrumb").children(".active").should("contain", "Data");
|
||||
});
|
||||
|
||||
it('.closest() - get closest ancestor DOM element', () => {
|
||||
// https://on.cypress.io/closest
|
||||
cy.get('.traversal-badge')
|
||||
.closest('ul')
|
||||
.should('have.class', 'list-group')
|
||||
})
|
||||
it(".closest() - get closest ancestor DOM element", () => {
|
||||
// https://on.cypress.io/closest
|
||||
cy.get(".traversal-badge").closest("ul").should("have.class", "list-group");
|
||||
});
|
||||
|
||||
it('.eq() - get a DOM element at a specific index', () => {
|
||||
// https://on.cypress.io/eq
|
||||
cy.get('.traversal-list>li')
|
||||
.eq(1).should('contain', 'siamese')
|
||||
})
|
||||
it(".eq() - get a DOM element at a specific index", () => {
|
||||
// https://on.cypress.io/eq
|
||||
cy.get(".traversal-list>li").eq(1).should("contain", "siamese");
|
||||
});
|
||||
|
||||
it('.filter() - get DOM elements that match the selector', () => {
|
||||
// https://on.cypress.io/filter
|
||||
cy.get('.traversal-nav>li')
|
||||
.filter('.active').should('contain', 'About')
|
||||
})
|
||||
it(".filter() - get DOM elements that match the selector", () => {
|
||||
// https://on.cypress.io/filter
|
||||
cy.get(".traversal-nav>li").filter(".active").should("contain", "About");
|
||||
});
|
||||
|
||||
it('.find() - get descendant DOM elements of the selector', () => {
|
||||
// https://on.cypress.io/find
|
||||
cy.get('.traversal-pagination')
|
||||
.find('li').find('a')
|
||||
.should('have.length', 7)
|
||||
})
|
||||
it(".find() - get descendant DOM elements of the selector", () => {
|
||||
// https://on.cypress.io/find
|
||||
cy.get(".traversal-pagination").find("li").find("a").should("have.length", 7);
|
||||
});
|
||||
|
||||
it('.first() - get first DOM element', () => {
|
||||
// https://on.cypress.io/first
|
||||
cy.get('.traversal-table td')
|
||||
.first().should('contain', '1')
|
||||
})
|
||||
it(".first() - get first DOM element", () => {
|
||||
// https://on.cypress.io/first
|
||||
cy.get(".traversal-table td").first().should("contain", "1");
|
||||
});
|
||||
|
||||
it('.last() - get last DOM element', () => {
|
||||
// https://on.cypress.io/last
|
||||
cy.get('.traversal-buttons .btn')
|
||||
.last().should('contain', 'Submit')
|
||||
})
|
||||
it(".last() - get last DOM element", () => {
|
||||
// https://on.cypress.io/last
|
||||
cy.get(".traversal-buttons .btn").last().should("contain", "Submit");
|
||||
});
|
||||
|
||||
it('.next() - get next sibling DOM element', () => {
|
||||
// https://on.cypress.io/next
|
||||
cy.get('.traversal-ul')
|
||||
.contains('apples').next().should('contain', 'oranges')
|
||||
})
|
||||
it(".next() - get next sibling DOM element", () => {
|
||||
// https://on.cypress.io/next
|
||||
cy.get(".traversal-ul").contains("apples").next().should("contain", "oranges");
|
||||
});
|
||||
|
||||
it('.nextAll() - get all next sibling DOM elements', () => {
|
||||
// https://on.cypress.io/nextall
|
||||
cy.get('.traversal-next-all')
|
||||
.contains('oranges')
|
||||
.nextAll().should('have.length', 3)
|
||||
})
|
||||
it(".nextAll() - get all next sibling DOM elements", () => {
|
||||
// https://on.cypress.io/nextall
|
||||
cy.get(".traversal-next-all").contains("oranges").nextAll().should("have.length", 3);
|
||||
});
|
||||
|
||||
it('.nextUntil() - get next sibling DOM elements until next el', () => {
|
||||
// https://on.cypress.io/nextuntil
|
||||
cy.get('#veggies')
|
||||
.nextUntil('#nuts').should('have.length', 3)
|
||||
})
|
||||
it(".nextUntil() - get next sibling DOM elements until next el", () => {
|
||||
// https://on.cypress.io/nextuntil
|
||||
cy.get("#veggies").nextUntil("#nuts").should("have.length", 3);
|
||||
});
|
||||
|
||||
it('.not() - remove DOM elements from set of DOM elements', () => {
|
||||
// https://on.cypress.io/not
|
||||
cy.get('.traversal-disabled .btn')
|
||||
.not('[disabled]').should('not.contain', 'Disabled')
|
||||
})
|
||||
it(".not() - remove DOM elements from set of DOM elements", () => {
|
||||
// https://on.cypress.io/not
|
||||
cy.get(".traversal-disabled .btn").not("[disabled]").should("not.contain", "Disabled");
|
||||
});
|
||||
|
||||
it('.parent() - get parent DOM element from DOM elements', () => {
|
||||
// https://on.cypress.io/parent
|
||||
cy.get('.traversal-mark')
|
||||
.parent().should('contain', 'Morbi leo risus')
|
||||
})
|
||||
it(".parent() - get parent DOM element from DOM elements", () => {
|
||||
// https://on.cypress.io/parent
|
||||
cy.get(".traversal-mark").parent().should("contain", "Morbi leo risus");
|
||||
});
|
||||
|
||||
it('.parents() - get parent DOM elements from DOM elements', () => {
|
||||
// https://on.cypress.io/parents
|
||||
cy.get('.traversal-cite')
|
||||
.parents().should('match', 'blockquote')
|
||||
})
|
||||
it(".parents() - get parent DOM elements from DOM elements", () => {
|
||||
// https://on.cypress.io/parents
|
||||
cy.get(".traversal-cite").parents().should("match", "blockquote");
|
||||
});
|
||||
|
||||
it('.parentsUntil() - get parent DOM elements from DOM elements until el', () => {
|
||||
// https://on.cypress.io/parentsuntil
|
||||
cy.get('.clothes-nav')
|
||||
.find('.active')
|
||||
.parentsUntil('.clothes-nav')
|
||||
.should('have.length', 2)
|
||||
})
|
||||
it(".parentsUntil() - get parent DOM elements from DOM elements until el", () => {
|
||||
// https://on.cypress.io/parentsuntil
|
||||
cy.get(".clothes-nav").find(".active").parentsUntil(".clothes-nav").should("have.length", 2);
|
||||
});
|
||||
|
||||
it('.prev() - get previous sibling DOM element', () => {
|
||||
// https://on.cypress.io/prev
|
||||
cy.get('.birds').find('.active')
|
||||
.prev().should('contain', 'Lorikeets')
|
||||
})
|
||||
it(".prev() - get previous sibling DOM element", () => {
|
||||
// https://on.cypress.io/prev
|
||||
cy.get(".birds").find(".active").prev().should("contain", "Lorikeets");
|
||||
});
|
||||
|
||||
it('.prevAll() - get all previous sibling DOM elements', () => {
|
||||
// https://on.cypress.io/prevall
|
||||
cy.get('.fruits-list').find('.third')
|
||||
.prevAll().should('have.length', 2)
|
||||
})
|
||||
it(".prevAll() - get all previous sibling DOM elements", () => {
|
||||
// https://on.cypress.io/prevall
|
||||
cy.get(".fruits-list").find(".third").prevAll().should("have.length", 2);
|
||||
});
|
||||
|
||||
it('.prevUntil() - get all previous sibling DOM elements until el', () => {
|
||||
// https://on.cypress.io/prevuntil
|
||||
cy.get('.foods-list').find('#nuts')
|
||||
.prevUntil('#veggies').should('have.length', 3)
|
||||
})
|
||||
it(".prevUntil() - get all previous sibling DOM elements until el", () => {
|
||||
// https://on.cypress.io/prevuntil
|
||||
cy.get(".foods-list").find("#nuts").prevUntil("#veggies").should("have.length", 3);
|
||||
});
|
||||
|
||||
it('.siblings() - get all sibling DOM elements', () => {
|
||||
// https://on.cypress.io/siblings
|
||||
cy.get('.traversal-pills .active')
|
||||
.siblings().should('have.length', 2)
|
||||
})
|
||||
})
|
||||
it(".siblings() - get all sibling DOM elements", () => {
|
||||
// https://on.cypress.io/siblings
|
||||
cy.get(".traversal-pills .active").siblings().should("have.length", 2);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,110 +1,108 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Utilities', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/utilities')
|
||||
})
|
||||
context("Utilities", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/utilities");
|
||||
});
|
||||
|
||||
it('Cypress._ - call a lodash method', () => {
|
||||
// https://on.cypress.io/_
|
||||
cy.request('https://jsonplaceholder.cypress.io/users')
|
||||
.then((response) => {
|
||||
let ids = Cypress._.chain(response.body).map('id').take(3).value()
|
||||
it("Cypress._ - call a lodash method", () => {
|
||||
// https://on.cypress.io/_
|
||||
cy.request("https://jsonplaceholder.cypress.io/users").then((response) => {
|
||||
let ids = Cypress._.chain(response.body).map("id").take(3).value();
|
||||
|
||||
expect(ids).to.deep.eq([1, 2, 3])
|
||||
})
|
||||
})
|
||||
expect(ids).to.deep.eq([1, 2, 3]);
|
||||
});
|
||||
});
|
||||
|
||||
it('Cypress.$ - call a jQuery method', () => {
|
||||
// https://on.cypress.io/$
|
||||
let $li = Cypress.$('.utility-jquery li:first')
|
||||
it("Cypress.$ - call a jQuery method", () => {
|
||||
// https://on.cypress.io/$
|
||||
let $li = Cypress.$(".utility-jquery li:first");
|
||||
|
||||
cy.wrap($li)
|
||||
.should('not.have.class', 'active')
|
||||
.click()
|
||||
.should('have.class', 'active')
|
||||
})
|
||||
cy.wrap($li).should("not.have.class", "active").click().should("have.class", "active");
|
||||
});
|
||||
|
||||
it('Cypress.Blob - blob utilities and base64 string conversion', () => {
|
||||
// https://on.cypress.io/blob
|
||||
cy.get('.utility-blob').then(($div) => {
|
||||
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
|
||||
// get the dataUrl string for the javascript-logo
|
||||
return Cypress.Blob.imgSrcToDataURL('https://example.cypress.io/assets/img/javascript-logo.png', undefined, 'anonymous')
|
||||
.then((dataUrl) => {
|
||||
// create an <img> element and set its src to the dataUrl
|
||||
let img = Cypress.$('<img />', {src: dataUrl})
|
||||
it("Cypress.Blob - blob utilities and base64 string conversion", () => {
|
||||
// https://on.cypress.io/blob
|
||||
cy.get(".utility-blob").then(($div) => {
|
||||
// https://github.com/nolanlawson/blob-util#imgSrcToDataURL
|
||||
// get the dataUrl string for the javascript-logo
|
||||
return Cypress.Blob.imgSrcToDataURL(
|
||||
"https://example.cypress.io/assets/img/javascript-logo.png",
|
||||
undefined,
|
||||
"anonymous"
|
||||
).then((dataUrl) => {
|
||||
// create an <img> element and set its src to the dataUrl
|
||||
let img = Cypress.$("<img />", { src: dataUrl });
|
||||
|
||||
// need to explicitly return cy here since we are initially returning
|
||||
// the Cypress.Blob.imgSrcToDataURL promise to our test
|
||||
// append the image
|
||||
$div.append(img)
|
||||
// need to explicitly return cy here since we are initially returning
|
||||
// the Cypress.Blob.imgSrcToDataURL promise to our test
|
||||
// append the image
|
||||
$div.append(img);
|
||||
|
||||
cy.get('.utility-blob img').click()
|
||||
.should('have.attr', 'src', dataUrl)
|
||||
})
|
||||
})
|
||||
})
|
||||
cy.get(".utility-blob img").click().should("have.attr", "src", dataUrl);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('Cypress.minimatch - test out glob patterns against strings', () => {
|
||||
// https://on.cypress.io/minimatch
|
||||
let matching = Cypress.minimatch('/users/1/comments', '/users/*/comments', {
|
||||
matchBase: true,
|
||||
})
|
||||
it("Cypress.minimatch - test out glob patterns against strings", () => {
|
||||
// https://on.cypress.io/minimatch
|
||||
let matching = Cypress.minimatch("/users/1/comments", "/users/*/comments", {
|
||||
matchBase: true
|
||||
});
|
||||
|
||||
expect(matching, 'matching wildcard').to.be.true
|
||||
expect(matching, "matching wildcard").to.be.true;
|
||||
|
||||
matching = Cypress.minimatch('/users/1/comments/2', '/users/*/comments', {
|
||||
matchBase: true,
|
||||
})
|
||||
matching = Cypress.minimatch("/users/1/comments/2", "/users/*/comments", {
|
||||
matchBase: true
|
||||
});
|
||||
|
||||
expect(matching, 'comments').to.be.false
|
||||
expect(matching, "comments").to.be.false;
|
||||
|
||||
// ** matches against all downstream path segments
|
||||
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/**', {
|
||||
matchBase: true,
|
||||
})
|
||||
// ** matches against all downstream path segments
|
||||
matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/**", {
|
||||
matchBase: true
|
||||
});
|
||||
|
||||
expect(matching, 'comments').to.be.true
|
||||
expect(matching, "comments").to.be.true;
|
||||
|
||||
// whereas * matches only the next path segment
|
||||
// whereas * matches only the next path segment
|
||||
|
||||
matching = Cypress.minimatch('/foo/bar/baz/123/quux?a=b&c=2', '/foo/*', {
|
||||
matchBase: false,
|
||||
})
|
||||
matching = Cypress.minimatch("/foo/bar/baz/123/quux?a=b&c=2", "/foo/*", {
|
||||
matchBase: false
|
||||
});
|
||||
|
||||
expect(matching, 'comments').to.be.false
|
||||
})
|
||||
expect(matching, "comments").to.be.false;
|
||||
});
|
||||
|
||||
it('Cypress.Promise - instantiate a bluebird promise', () => {
|
||||
// https://on.cypress.io/promise
|
||||
let waited = false
|
||||
it("Cypress.Promise - instantiate a bluebird promise", () => {
|
||||
// https://on.cypress.io/promise
|
||||
let waited = false;
|
||||
|
||||
/**
|
||||
* @return Bluebird<string>
|
||||
*/
|
||||
function waitOneSecond() {
|
||||
// return a promise that resolves after 1 second
|
||||
// @ts-ignore TS2351 (new Cypress.Promise)
|
||||
return new Cypress.Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
// set waited to true
|
||||
waited = true
|
||||
/**
|
||||
* @return Bluebird<string>
|
||||
*/
|
||||
function waitOneSecond() {
|
||||
// return a promise that resolves after 1 second
|
||||
// @ts-ignore TS2351 (new Cypress.Promise)
|
||||
return new Cypress.Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
// set waited to true
|
||||
waited = true;
|
||||
|
||||
// resolve with 'foo' string
|
||||
resolve('foo')
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
// resolve with 'foo' string
|
||||
resolve("foo");
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
|
||||
cy.then(() => {
|
||||
// return a promise to cy.then() that
|
||||
// is awaited until it resolves
|
||||
// @ts-ignore TS7006
|
||||
return waitOneSecond().then((str) => {
|
||||
expect(str).to.eq('foo')
|
||||
expect(waited).to.be.true
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
cy.then(() => {
|
||||
// return a promise to cy.then() that
|
||||
// is awaited until it resolves
|
||||
// @ts-ignore TS7006
|
||||
return waitOneSecond().then((str) => {
|
||||
expect(str).to.eq("foo");
|
||||
expect(waited).to.be.true;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Viewport', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/viewport')
|
||||
})
|
||||
context("Viewport", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/viewport");
|
||||
});
|
||||
|
||||
it('cy.viewport() - set the viewport size and dimension', () => {
|
||||
// https://on.cypress.io/viewport
|
||||
it("cy.viewport() - set the viewport size and dimension", () => {
|
||||
// https://on.cypress.io/viewport
|
||||
|
||||
cy.get('#navbar').should('be.visible')
|
||||
cy.viewport(320, 480)
|
||||
cy.get("#navbar").should("be.visible");
|
||||
cy.viewport(320, 480);
|
||||
|
||||
// the navbar should have collapse since our screen is smaller
|
||||
cy.get('#navbar').should('not.be.visible')
|
||||
cy.get('.navbar-toggle').should('be.visible').click()
|
||||
cy.get('.nav').find('a').should('be.visible')
|
||||
// the navbar should have collapse since our screen is smaller
|
||||
cy.get("#navbar").should("not.be.visible");
|
||||
cy.get(".navbar-toggle").should("be.visible").click();
|
||||
cy.get(".nav").find("a").should("be.visible");
|
||||
|
||||
// lets see what our app looks like on a super large screen
|
||||
cy.viewport(2999, 2999)
|
||||
// lets see what our app looks like on a super large screen
|
||||
cy.viewport(2999, 2999);
|
||||
|
||||
// cy.viewport() accepts a set of preset sizes
|
||||
// to easily set the screen to a device's width and height
|
||||
// cy.viewport() accepts a set of preset sizes
|
||||
// to easily set the screen to a device's width and height
|
||||
|
||||
// We added a cy.wait() between each viewport change so you can see
|
||||
// the change otherwise it is a little too fast to see :)
|
||||
// We added a cy.wait() between each viewport change so you can see
|
||||
// the change otherwise it is a little too fast to see :)
|
||||
|
||||
cy.viewport('macbook-15')
|
||||
cy.wait(200)
|
||||
cy.viewport('macbook-13')
|
||||
cy.wait(200)
|
||||
cy.viewport('macbook-11')
|
||||
cy.wait(200)
|
||||
cy.viewport('ipad-2')
|
||||
cy.wait(200)
|
||||
cy.viewport('ipad-mini')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-6+')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-6')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-5')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-4')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-3')
|
||||
cy.wait(200)
|
||||
cy.viewport("macbook-15");
|
||||
cy.wait(200);
|
||||
cy.viewport("macbook-13");
|
||||
cy.wait(200);
|
||||
cy.viewport("macbook-11");
|
||||
cy.wait(200);
|
||||
cy.viewport("ipad-2");
|
||||
cy.wait(200);
|
||||
cy.viewport("ipad-mini");
|
||||
cy.wait(200);
|
||||
cy.viewport("iphone-6+");
|
||||
cy.wait(200);
|
||||
cy.viewport("iphone-6");
|
||||
cy.wait(200);
|
||||
cy.viewport("iphone-5");
|
||||
cy.wait(200);
|
||||
cy.viewport("iphone-4");
|
||||
cy.wait(200);
|
||||
cy.viewport("iphone-3");
|
||||
cy.wait(200);
|
||||
|
||||
// cy.viewport() accepts an orientation for all presets
|
||||
// the default orientation is 'portrait'
|
||||
cy.viewport('ipad-2', 'portrait')
|
||||
cy.wait(200)
|
||||
cy.viewport('iphone-4', 'landscape')
|
||||
cy.wait(200)
|
||||
// cy.viewport() accepts an orientation for all presets
|
||||
// the default orientation is 'portrait'
|
||||
cy.viewport("ipad-2", "portrait");
|
||||
cy.wait(200);
|
||||
cy.viewport("iphone-4", "landscape");
|
||||
cy.wait(200);
|
||||
|
||||
// The viewport will be reset back to the default dimensions
|
||||
// in between tests (the default can be set in cypress.json)
|
||||
})
|
||||
})
|
||||
// The viewport will be reset back to the default dimensions
|
||||
// in between tests (the default can be set in cypress.json)
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Waiting', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/waiting')
|
||||
})
|
||||
// BE CAREFUL of adding unnecessary wait times.
|
||||
// https://on.cypress.io/best-practices#Unnecessary-Waiting
|
||||
context("Waiting", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/waiting");
|
||||
});
|
||||
// BE CAREFUL of adding unnecessary wait times.
|
||||
// https://on.cypress.io/best-practices#Unnecessary-Waiting
|
||||
|
||||
// https://on.cypress.io/wait
|
||||
it('cy.wait() - wait for a specific amount of time', () => {
|
||||
cy.get('.wait-input1').type('Wait 1000ms after typing')
|
||||
cy.wait(1000)
|
||||
cy.get('.wait-input2').type('Wait 1000ms after typing')
|
||||
cy.wait(1000)
|
||||
cy.get('.wait-input3').type('Wait 1000ms after typing')
|
||||
cy.wait(1000)
|
||||
})
|
||||
// https://on.cypress.io/wait
|
||||
it("cy.wait() - wait for a specific amount of time", () => {
|
||||
cy.get(".wait-input1").type("Wait 1000ms after typing");
|
||||
cy.wait(1000);
|
||||
cy.get(".wait-input2").type("Wait 1000ms after typing");
|
||||
cy.wait(1000);
|
||||
cy.get(".wait-input3").type("Wait 1000ms after typing");
|
||||
cy.wait(1000);
|
||||
});
|
||||
|
||||
it('cy.wait() - wait for a specific route', () => {
|
||||
// Listen to GET to comments/1
|
||||
cy.intercept('GET', '**/comments/*').as('getComment')
|
||||
it("cy.wait() - wait for a specific route", () => {
|
||||
// Listen to GET to comments/1
|
||||
cy.intercept("GET", "**/comments/*").as("getComment");
|
||||
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get('.network-btn').click()
|
||||
// we have code that gets a comment when
|
||||
// the button is clicked in scripts.js
|
||||
cy.get(".network-btn").click();
|
||||
|
||||
// wait for GET comments/1
|
||||
cy.wait('@getComment').its('response.statusCode').should('be.oneOf', [200, 304])
|
||||
})
|
||||
})
|
||||
// wait for GET comments/1
|
||||
cy.wait("@getComment").its("response.statusCode").should("be.oneOf", [200, 304]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
context('Window', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('https://example.cypress.io/commands/window')
|
||||
})
|
||||
context("Window", () => {
|
||||
beforeEach(() => {
|
||||
cy.visit("https://example.cypress.io/commands/window");
|
||||
});
|
||||
|
||||
it('cy.window() - get the global window object', () => {
|
||||
// https://on.cypress.io/window
|
||||
cy.window().should('have.property', 'top')
|
||||
})
|
||||
it("cy.window() - get the global window object", () => {
|
||||
// https://on.cypress.io/window
|
||||
cy.window().should("have.property", "top");
|
||||
});
|
||||
|
||||
it('cy.document() - get the document object', () => {
|
||||
// https://on.cypress.io/document
|
||||
cy.document().should('have.property', 'charset').and('eq', 'UTF-8')
|
||||
})
|
||||
it("cy.document() - get the document object", () => {
|
||||
// https://on.cypress.io/document
|
||||
cy.document().should("have.property", "charset").and("eq", "UTF-8");
|
||||
});
|
||||
|
||||
it('cy.title() - get the title', () => {
|
||||
// https://on.cypress.io/title
|
||||
cy.title().should('include', 'Kitchen Sink')
|
||||
})
|
||||
})
|
||||
it("cy.title() - get the title", () => {
|
||||
// https://on.cypress.io/title
|
||||
cy.title().should("include", "Kitchen Sink");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
"id": 8739,
|
||||
"name": "Jane",
|
||||
"email": "jane@example.com"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
// This example plugins/index.jsx can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
@@ -17,6 +17,6 @@
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// This example support/index.jsx is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
@@ -14,7 +14,7 @@
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands'
|
||||
import "./commands";
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
|
||||
@@ -2,11 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"baseUrl": "../node_modules",
|
||||
"types": [
|
||||
"cypress"
|
||||
]
|
||||
"types": ["cypress"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.*"
|
||||
]
|
||||
"include": ["**/*.*"]
|
||||
}
|
||||
|
||||
2
client/dev-dist/registerSW.js
Normal file
@@ -0,0 +1,2 @@
|
||||
if ("serviceWorker" in navigator)
|
||||
navigator.serviceWorker.register("/dev-sw.js?dev-sw", { scope: "/", type: "classic" });
|
||||
96
client/dev-dist/sw.js
Normal file
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright 2018 Google Inc. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// If the loader is already loaded, just stop.
|
||||
if (!self.define) {
|
||||
let registry = {};
|
||||
|
||||
// Used for `eval` and `importScripts` where we can't get script URL by other means.
|
||||
// In both cases, it's safe to use a global var because those functions are synchronous.
|
||||
let nextDefineUri;
|
||||
|
||||
const singleRequire = (uri, parentUri) => {
|
||||
uri = new URL(uri + ".js", parentUri).href;
|
||||
return (
|
||||
registry[uri] ||
|
||||
new Promise((resolve) => {
|
||||
if ("document" in self) {
|
||||
const script = document.createElement("script");
|
||||
script.src = uri;
|
||||
script.onload = resolve;
|
||||
document.head.appendChild(script);
|
||||
} else {
|
||||
nextDefineUri = uri;
|
||||
importScripts(uri);
|
||||
resolve();
|
||||
}
|
||||
}).then(() => {
|
||||
let promise = registry[uri];
|
||||
if (!promise) {
|
||||
throw new Error(`Module ${uri} didn’t register its module`);
|
||||
}
|
||||
return promise;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
self.define = (depsNames, factory) => {
|
||||
const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href;
|
||||
if (registry[uri]) {
|
||||
// Module is already loading or loaded.
|
||||
return;
|
||||
}
|
||||
let exports = {};
|
||||
const require = (depUri) => singleRequire(depUri, uri);
|
||||
const specialDeps = {
|
||||
module: { uri },
|
||||
exports,
|
||||
require
|
||||
};
|
||||
registry[uri] = Promise.all(depsNames.map((depName) => specialDeps[depName] || require(depName))).then((deps) => {
|
||||
factory(...deps);
|
||||
return exports;
|
||||
});
|
||||
};
|
||||
}
|
||||
define(["./workbox-b5f7729d"], function (workbox) {
|
||||
"use strict";
|
||||
|
||||
self.skipWaiting();
|
||||
workbox.clientsClaim();
|
||||
|
||||
/**
|
||||
* The precacheAndRoute() method efficiently caches and responds to
|
||||
* requests for URLs in the manifest.
|
||||
* See https://goo.gl/S9QRab
|
||||
*/
|
||||
workbox.precacheAndRoute(
|
||||
[
|
||||
{
|
||||
url: "registerSW.js",
|
||||
revision: "3ca0b8505b4bec776b69afdba2768812"
|
||||
},
|
||||
{
|
||||
url: "index.html",
|
||||
revision: "0.sa702m4aq68"
|
||||
}
|
||||
],
|
||||
{}
|
||||
);
|
||||
workbox.cleanupOutdatedCaches();
|
||||
workbox.registerRoute(
|
||||
new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {
|
||||
allowlist: [/^\/$/]
|
||||
})
|
||||
);
|
||||
});
|
||||
3435
client/dev-dist/workbox-b5f7729d.js
Normal file
123
client/index.html
Normal file
@@ -0,0 +1,123 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
||||
<link rel="icon" href="/favicon.png"/>
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
||||
<link rel="icon" href="/ro-favicon.png"/>
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
||||
<link rel="icon" href="/pm/pm-favicon.ico"/>
|
||||
<% } %>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta name="theme-color" content="#1690ff"/>
|
||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||
<!-- TODO:AIo Update the individual logos for each.-->
|
||||
<link rel="apple-touch-icon" href="public/logo192.png"/>
|
||||
<link rel="mask-icon" href="/mask-icon.svg" color="#FFFFFF">
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<% if (env.VITE_APP_INSTANCE === 'IMEX') { %>
|
||||
<meta name="description" content="ImEX Online"/>
|
||||
<title>ImEX Online</title>
|
||||
<script type="text/javascript">
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = '36724f62-2eb0-4b29-9cdd-9905fb99913e';
|
||||
(function () {
|
||||
d = document;
|
||||
s = d.createElement('script');
|
||||
s.src = 'https://client.crisp.chat/l.js';
|
||||
s.async = 1;
|
||||
d.getElementsByTagName('head')[0].appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'ROME') { %>
|
||||
<meta name="description" content="Rome Online"/>
|
||||
<title>Rome Online</title>
|
||||
<script type="text/javascript" id="zsiqchat">
|
||||
var $zoho = $zoho || {};
|
||||
$zoho.salesiq = $zoho.salesiq || {
|
||||
widgetcode: "siq01bb8ac617280bdacddfeb528f07734dadc64ef3f05efef9f769c1ec171af666",
|
||||
values: {},
|
||||
ready: function () {
|
||||
}
|
||||
};
|
||||
var d = document;
|
||||
s = d.createElement("script");
|
||||
s.type = "text/javascript";
|
||||
s.id = "zsiqscript";
|
||||
s.defer = true;
|
||||
s.src = "https://salesiq.zohopublic.com/widget";
|
||||
t = d.getElementsByTagName("script")[0];
|
||||
t.parentNode.insertBefore(s, t);
|
||||
</script>
|
||||
|
||||
<% } %> <% if (env.VITE_APP_INSTANCE === 'PROMANAGER') { %>
|
||||
<title>ProManager</title>
|
||||
<meta name="description" content="ProManager"/>
|
||||
|
||||
<% } %>
|
||||
<script>
|
||||
!(function () {
|
||||
'use strict';
|
||||
var e = [
|
||||
'debug',
|
||||
'destroy',
|
||||
'do',
|
||||
'help',
|
||||
'identify',
|
||||
'is',
|
||||
'off',
|
||||
'on',
|
||||
'ready',
|
||||
'render',
|
||||
'reset',
|
||||
'safe',
|
||||
'set',
|
||||
];
|
||||
if (window.noticeable) console.warn('Noticeable SDK code snippet loaded more than once');
|
||||
else {
|
||||
var n = (window.noticeable = window.noticeable || []);
|
||||
|
||||
function t(e) {
|
||||
return function () {
|
||||
var t = Array.prototype.slice.call(arguments);
|
||||
return t.unshift(e), n.push(t), n;
|
||||
};
|
||||
}
|
||||
|
||||
!(function () {
|
||||
for (var o = 0; o < e.length; o++) {
|
||||
var r = e[o];
|
||||
n[r] = t(r);
|
||||
}
|
||||
})(),
|
||||
(function () {
|
||||
var e = document.createElement('script');
|
||||
(e.async = !0), (e.src = 'https://sdk.noticeable.io/l.js');
|
||||
var n = document.head;
|
||||
n.insertBefore(e, n.firstChild);
|
||||
})();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
|
||||
<script type="module" src="src/index.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
18953
client/package-lock.json
generated
@@ -1,103 +1,107 @@
|
||||
{
|
||||
"name": "bodyshop",
|
||||
"version": "0.2.1",
|
||||
"engines": {
|
||||
"node": ">=18.18.2"
|
||||
},
|
||||
"type": "module",
|
||||
"private": true,
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
"@ant-design/compatible": "^5.1.2",
|
||||
"@ant-design/pro-layout": "^7.17.16",
|
||||
"@apollo/client": "^3.8.10",
|
||||
"@asseinfo/react-kanban": "^2.2.0",
|
||||
"@craco/craco": "^7.1.0",
|
||||
"@fingerprintjs/fingerprintjs": "^4.2.2",
|
||||
"@ant-design/pro-layout": "^7.19.11",
|
||||
"@apollo/client": "^3.10.8",
|
||||
"@emotion/is-prop-valid": "^1.3.0",
|
||||
"@fingerprintjs/fingerprintjs": "^4.4.3",
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@reduxjs/toolkit": "^2.2.1",
|
||||
"@sentry/cli": "^2.28.6",
|
||||
"@sentry/react": "^7.104.0",
|
||||
"@sentry/tracing": "^7.104.0",
|
||||
"@splitsoftware/splitio-react": "^1.11.0",
|
||||
"@reduxjs/toolkit": "^2.2.6",
|
||||
"@sentry/cli": "^2.32.2",
|
||||
"@sentry/react": "^7.114.0",
|
||||
"@splitsoftware/splitio-react": "^1.12.0",
|
||||
"@tanem/react-nprogress": "^5.0.51",
|
||||
"antd": "^5.14.2",
|
||||
"@vitejs/plugin-react": "^4.3.1",
|
||||
"antd": "^5.19.3",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"apollo-link-sentry": "^3.3.0",
|
||||
"axios": "^1.6.7",
|
||||
"craco-less": "^3.0.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"autosize": "^6.0.1",
|
||||
"axios": "^1.6.8",
|
||||
"classnames": "^2.5.1",
|
||||
"css-box-model": "^1.2.1",
|
||||
"dayjs": "^1.11.12",
|
||||
"dayjs-business-days2": "^1.2.2",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^10.8.1",
|
||||
"graphql": "^16.6.0",
|
||||
"i18next": "^23.10.0",
|
||||
"i18next-browser-languagedetector": "^7.0.2",
|
||||
"jsoneditor": "^10.0.1",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.10.57",
|
||||
"logrocket": "^8.0.1",
|
||||
"markerjs2": "^2.32.0",
|
||||
"normalize-url": "^8.0.0",
|
||||
"phone": "^3.1.42",
|
||||
"preval.macro": "^5.0.0",
|
||||
"firebase": "^10.12.4",
|
||||
"graphql": "^16.9.0",
|
||||
"i18next": "^23.12.2",
|
||||
"i18next-browser-languagedetector": "^8.0.0",
|
||||
"immutability-helper": "^3.1.1",
|
||||
"libphonenumber-js": "^1.11.4",
|
||||
"logrocket": "^8.1.1",
|
||||
"markerjs2": "^2.32.1",
|
||||
"memoize-one": "^6.0.0",
|
||||
"normalize-url": "^8.0.1",
|
||||
"object-hash": "^3.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "^9.0.0",
|
||||
"rc-queue-anim": "^2.0.0",
|
||||
"rc-scroll-anim": "^2.7.6",
|
||||
"react": "^18.2.0",
|
||||
"react-big-calendar": "^1.11.0",
|
||||
"raf-schd": "^4.0.3",
|
||||
"react": "^18.3.1",
|
||||
"react-big-calendar": "^1.13.1",
|
||||
"react-color": "^2.19.3",
|
||||
"react-cookie": "^7.1.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-cookie": "^7.1.4",
|
||||
"react-dom": "^18.3.1",
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.0",
|
||||
"react-grid-gallery": "^1.0.1",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-i18next": "^14.0.5",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-i18next": "^14.1.3",
|
||||
"react-icons": "^5.2.1",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
"react-intersection-observer": "^9.8.1",
|
||||
"react-joyride": "^2.8.2",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-number-format": "^5.3.3",
|
||||
"react-redux": "^9.1.0",
|
||||
"react-number-format": "^5.4.0",
|
||||
"react-popopo": "^2.1.9",
|
||||
"react-product-fruits": "^2.2.6",
|
||||
"react-redux": "^9.1.2",
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-router-dom": "^6.22.2",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-router-dom": "^6.25.1",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.5",
|
||||
"recharts": "^2.12.2",
|
||||
"react-virtuoso": "^4.7.12",
|
||||
"recharts": "^2.12.7",
|
||||
"redux": "^5.0.1",
|
||||
"redux-actions": "^3.0.0",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.3.0",
|
||||
"redux-state-sync": "^3.1.4",
|
||||
"reselect": "^5.1.0",
|
||||
"sass": "^1.71.1",
|
||||
"socket.io-client": "^4.7.4",
|
||||
"styled-components": "^6.1.8",
|
||||
"reselect": "^5.1.1",
|
||||
"sass": "^1.77.8",
|
||||
"socket.io-client": "^4.7.5",
|
||||
"styled-components": "^6.1.12",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"web-vitals": "^3.5.2",
|
||||
"workbox-core": "^7.0.0",
|
||||
"workbox-expiration": "^7.0.0",
|
||||
"workbox-navigation-preload": "^7.0.0",
|
||||
"workbox-precaching": "^7.0.0",
|
||||
"workbox-routing": "^7.0.0",
|
||||
"workbox-strategies": "^7.0.0",
|
||||
"yauzl": "^3.1.1"
|
||||
"use-memo-one": "^1.1.3",
|
||||
"userpilot": "^1.3.2",
|
||||
"vite-plugin-ejs": "^1.7.0",
|
||||
"web-vitals": "^3.5.2"
|
||||
},
|
||||
"scripts": {
|
||||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||
"start": "craco start",
|
||||
"build": "REACT_APP_GIT_SHA=`git rev-parse --short HEAD` craco build",
|
||||
"build:test": "env-cmd -f .env.test npm run build",
|
||||
"build-deploy:test": "npm run build:test && s3cmd sync build/* s3://imex-online-test && echo '🚀 TESTING Deployed!'",
|
||||
"buildcra": "REACT_APP_GIT_SHA=`git rev-parse --short HEAD` craco build",
|
||||
"start": "vite",
|
||||
"build": "dotenvx run --env-file=.env.development.imex -- vite build",
|
||||
"start:imex": "dotenvx run --env-file=.env.development.imex -- vite",
|
||||
"start:rome": "dotenvx run --env-file=.env.development.rome -- vite",
|
||||
"start:promanager": "dotenvx run --env-file=.env.development.promanager -- vite",
|
||||
"build:test:imex": "env-cmd -f .env.test.imex npm run build",
|
||||
"build:test:rome": "env-cmd -f .env.test.rome npm run build",
|
||||
"build:test:promanager": "env-cmd -f .env.test.promanager npm run build",
|
||||
"build:production:imex": "env-cmd -f .env.production.imex npm run build",
|
||||
"build:production:rome": "env-cmd -f .env.production.rome npm run build",
|
||||
"build:production:promanager": "env-cmd -f .env.production.promanager npm run build",
|
||||
"test": "cypress open",
|
||||
"eject": "react-scripts eject",
|
||||
"madge": "madge --image ./madge-graph.svg --extensions js,jsx,ts,tsx --circular .",
|
||||
"eulaize": "node src/utils/eulaize.js",
|
||||
"sentry:sourcemaps": "sentry-cli sourcemaps inject --org imex --project imexonline ./build && sentry-cli sourcemaps upload --org imex --project imexonline ./build"
|
||||
"sentry:sourcemaps:imex": "sentry-cli sourcemaps inject --org imex --project imexonline ./build && sentry-cli sourcemaps upload --org imex --project imexonline ./build"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
@@ -121,14 +125,35 @@
|
||||
"resolutions": {
|
||||
"react-error-overlay": "6.0.9"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-x64-gnu": "4.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@sentry/webpack-plugin": "^2.14.2",
|
||||
"@testing-library/cypress": "^10.0.1",
|
||||
"cypress": "^13.6.6",
|
||||
"@babel/preset-react": "^7.24.7",
|
||||
"@dotenvx/dotenvx": "^1.6.4",
|
||||
"@emotion/babel-plugin": "^11.12.0",
|
||||
"@emotion/react": "^11.12.0",
|
||||
"@sentry/webpack-plugin": "^2.21.1",
|
||||
"@testing-library/cypress": "^10.0.2",
|
||||
"browserslist": "^4.23.2",
|
||||
"browserslist-to-esbuild": "^2.1.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"cypress": "^13.13.1",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"memfs": "^4.9.3",
|
||||
"os-browserify": "^0.3.0",
|
||||
"react-error-overlay": "6.0.11",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.3"
|
||||
"source-map-explorer": "^2.5.3",
|
||||
"vite": "^5.3.4",
|
||||
"vite-plugin-babel": "^1.2.0",
|
||||
"vite-plugin-eslint": "^1.8.1",
|
||||
"vite-plugin-legacy": "^2.1.0",
|
||||
"vite-plugin-node-polyfills": "^0.22.0",
|
||||
"vite-plugin-pwa": "^0.20.0",
|
||||
"vite-plugin-style-import": "^2.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16422,7 +16422,7 @@ For when you don't want to write the same thing over and over to cache a method
|
||||
$ npm install --save-dev stubs
|
||||
```
|
||||
```js
|
||||
var mylib = require('./lib/index.js')
|
||||
var mylib = require('./lib/index.jsx')
|
||||
var stubs = require('stubs')
|
||||
|
||||
// make it a noop
|
||||
|
||||
@@ -16567,7 +16567,7 @@ even more slower.
|
||||
## Benchmarks
|
||||
|
||||
```bash
|
||||
$ node benchmarks/index.js
|
||||
$ node benchmarks/index.jsx
|
||||
Benchmarking: sign
|
||||
elliptic#sign x 262 ops/sec ±0.51% (177 runs sampled)
|
||||
eccjs#sign x 55.91 ops/sec ±0.90% (144 runs sampled)
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
// unlayer.registerPropertyEditor({
|
||||
// name: "field_name",
|
||||
// layout: "bottom",
|
||||
// Widget: unlayer.createWidget({
|
||||
// render(value) {
|
||||
// return `
|
||||
// <input class="field" value=${value} />
|
||||
// `;
|
||||
// },
|
||||
// mount(node, value, updateValue) {
|
||||
// var input = node.getElementsByClassName("field")[0];
|
||||
// input.onchange = function (event) {
|
||||
// updateValue(event.target.value);
|
||||
// };
|
||||
// },
|
||||
// }),
|
||||
// });
|
||||
|
||||
// unlayer.registerTool({
|
||||
// type: "whatever",
|
||||
// category: "contents",
|
||||
// label: "Begin Repeat",
|
||||
// icon: "fa-smile",
|
||||
// values: {},
|
||||
// options: {
|
||||
// default: {
|
||||
// title: null,
|
||||
// },
|
||||
// text: {
|
||||
// title: "Field",
|
||||
// position: 1,
|
||||
// options: {
|
||||
// field: {
|
||||
// label: "Field",
|
||||
// defaultValue: "",
|
||||
// widget: "field_name",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// renderer: {
|
||||
// Viewer: unlayer.createViewer({
|
||||
// render(values) {
|
||||
// console.log(values);
|
||||
// return `
|
||||
// <div style="display: none;">{{#each ${values.field}}}</div>
|
||||
// `;
|
||||
// },
|
||||
// }),
|
||||
// exporters: {
|
||||
// web: function () {},
|
||||
// email: function () {},
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
// unlayer.registerTool({
|
||||
// type: "whatever",
|
||||
// category: "contents",
|
||||
// label: "End Repeat",
|
||||
// icon: "fa-smile",
|
||||
// values: {},
|
||||
// options: {
|
||||
// default: {
|
||||
// title: null,
|
||||
// },
|
||||
// text: {
|
||||
// title: "Field",
|
||||
// position: 1,
|
||||
// options: {
|
||||
// field: {
|
||||
// label: "Field",
|
||||
// defaultValue: "",
|
||||
// widget: "field_name",
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// renderer: {
|
||||
// Viewer: unlayer.createViewer({
|
||||
// render(values) {
|
||||
// return `
|
||||
// <div style="display: none;">{{ /each }}</div>
|
||||
// `;
|
||||
// },
|
||||
// }),
|
||||
// exporters: {
|
||||
// web: function () {},
|
||||
// email: function () {},
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
|
||||
unlayer.registerColumns([2, 2, 2, 2, 2, 2]);
|
||||
unlayer.registerColumns([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]);
|
||||
@@ -5,41 +5,41 @@ importScripts("https://www.gstatic.com/firebasejs/8.2.0/firebase-messaging.js");
|
||||
// Initialize the Firebase app in the service worker by passing the generated config
|
||||
let firebaseConfig;
|
||||
switch (this.location.hostname) {
|
||||
case "localhost":
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc",
|
||||
authDomain: "imex-dev.firebaseapp.com",
|
||||
databaseURL: "https://imex-dev.firebaseio.com",
|
||||
projectId: "imex-dev",
|
||||
storageBucket: "imex-dev.appspot.com",
|
||||
messagingSenderId: "759548147434",
|
||||
appId: "1:759548147434:web:e8239868a48ceb36700993",
|
||||
measurementId: "G-K5XRBVVB4S",
|
||||
};
|
||||
break;
|
||||
case "test.imex.online":
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c",
|
||||
authDomain: "imex-test.firebaseapp.com",
|
||||
projectId: "imex-test",
|
||||
storageBucket: "imex-test.appspot.com",
|
||||
messagingSenderId: "991923618608",
|
||||
appId: "1:991923618608:web:633437569cdad78299bef5",
|
||||
// measurementId: "${config.measurementId}",
|
||||
};
|
||||
break;
|
||||
case "imex.online":
|
||||
default:
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU",
|
||||
authDomain: "imex-prod.firebaseapp.com",
|
||||
databaseURL: "https://imex-prod.firebaseio.com",
|
||||
projectId: "imex-prod",
|
||||
storageBucket: "imex-prod.appspot.com",
|
||||
messagingSenderId: "253497221485",
|
||||
appId: "1:253497221485:web:3c81c483b94db84b227a64",
|
||||
measurementId: "G-NTWBKG2L0M",
|
||||
};
|
||||
case "localhost":
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyDPLT8GiDHDR1R4nI66Qi0BY1aYviDPioc",
|
||||
authDomain: "imex-dev.firebaseapp.com",
|
||||
databaseURL: "https://imex-dev.firebaseio.com",
|
||||
projectId: "imex-dev",
|
||||
storageBucket: "imex-dev.appspot.com",
|
||||
messagingSenderId: "759548147434",
|
||||
appId: "1:759548147434:web:e8239868a48ceb36700993",
|
||||
measurementId: "G-K5XRBVVB4S",
|
||||
};
|
||||
break;
|
||||
case "test.imex.online":
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyBw7_GTy7GtQyfkIRPVrWHEGKfcqeyXw0c",
|
||||
authDomain: "imex-test.firebaseapp.com",
|
||||
projectId: "imex-test",
|
||||
storageBucket: "imex-test.appspot.com",
|
||||
messagingSenderId: "991923618608",
|
||||
appId: "1:991923618608:web:633437569cdad78299bef5",
|
||||
// measurementId: "${config.measurementId}",
|
||||
};
|
||||
break;
|
||||
case "imex.online":
|
||||
default:
|
||||
firebaseConfig = {
|
||||
apiKey: "AIzaSyDSezy-jGJreo7ulgpLdlpOwAOrgcaEkhU",
|
||||
authDomain: "imex-prod.firebaseapp.com",
|
||||
databaseURL: "https://imex-prod.firebaseio.com",
|
||||
projectId: "imex-prod",
|
||||
storageBucket: "imex-prod.appspot.com",
|
||||
messagingSenderId: "253497221485",
|
||||
appId: "1:253497221485:web:3c81c483b94db84b227a64",
|
||||
measurementId: "G-NTWBKG2L0M",
|
||||
};
|
||||
}
|
||||
|
||||
firebase.initializeApp(firebaseConfig);
|
||||
@@ -48,9 +48,9 @@ firebase.initializeApp(firebaseConfig);
|
||||
const messaging = firebase.messaging();
|
||||
|
||||
messaging.onBackgroundMessage(function (payload) {
|
||||
// Customize notification here
|
||||
const channel = new BroadcastChannel("imex-sw-messages");
|
||||
channel.postMessage(payload);
|
||||
// Customize notification here
|
||||
const channel = new BroadcastChannel("imex-sw-messages");
|
||||
channel.postMessage(payload);
|
||||
|
||||
//self.registration.showNotification(notificationTitle, notificationOptions);
|
||||
//self.registration.showNotification(notificationTitle, notificationOptions);
|
||||
});
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<link href="%PUBLIC_URL%/favicon.png" rel="icon"/>
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<meta content="#002366" name="theme-color"/>
|
||||
<meta content="ImEX Online" name="description"/>
|
||||
<!-- <link rel="apple-touch-icon" href="logo192.png" /> -->
|
||||
<link href="logo192.png" rel="apple-touch-icon"/>
|
||||
<script type="text/javascript">
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = "36724f62-2eb0-4b29-9cdd-9905fb99913e";
|
||||
(function () {
|
||||
d = document;
|
||||
s = d.createElement("script");
|
||||
s.src = "https://client.crisp.chat/l.js";
|
||||
s.async = 1;
|
||||
d.getElementsByTagName("head")[0].appendChild(s);
|
||||
})();
|
||||
</script>
|
||||
<script>
|
||||
!(function () {
|
||||
"use strict";
|
||||
var e = [
|
||||
"debug",
|
||||
"destroy",
|
||||
"do",
|
||||
"help",
|
||||
"identify",
|
||||
"is",
|
||||
"off",
|
||||
"on",
|
||||
"ready",
|
||||
"render",
|
||||
"reset",
|
||||
"safe",
|
||||
"set",
|
||||
];
|
||||
if (window.noticeable)
|
||||
console.warn("Noticeable SDK code snippet loaded more than once");
|
||||
else {
|
||||
var n = (window.noticeable = window.noticeable || []);
|
||||
|
||||
function t(e) {
|
||||
return function () {
|
||||
var t = Array.prototype.slice.call(arguments);
|
||||
return t.unshift(e), n.push(t), n;
|
||||
};
|
||||
}
|
||||
|
||||
!(function () {
|
||||
for (var o = 0; o < e.length; o++) {
|
||||
var r = e[o];
|
||||
n[r] = t(r);
|
||||
}
|
||||
})(),
|
||||
(function () {
|
||||
var e = document.createElement("script");
|
||||
(e.async = !0), (e.src = "https://sdk.noticeable.io/l.js");
|
||||
var n = document.head;
|
||||
n.insertBefore(e, n.firstChild);
|
||||
})();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
||||
<!--
|
||||
manifest.json provides metadata used when your web app is installed on a
|
||||
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
|
||||
-->
|
||||
<link href="%PUBLIC_URL%/manifest.json" rel="manifest"/>
|
||||
<!--
|
||||
Notice the use of %PUBLIC_URL% in the tags above.
|
||||
It will be replaced with the URL of the `public` folder during the build.
|
||||
Only files inside the `public` folder can be referenced from the HTML.
|
||||
|
||||
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>ImEX Online</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,27 +0,0 @@
|
||||
{
|
||||
"short_name": "ImEX Online",
|
||||
"name": "ImEX Online",
|
||||
"description": "The ultimate bodyshop management system.",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "logo192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "logo1024.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#fff",
|
||||
"background_color": "#fff",
|
||||
"gcm_sender_id": "103953800507"
|
||||
}
|
||||
BIN
client/public/pm/pm-apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
client/public/pm/pm-favicon.ico
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
client/public/pm/pm-icon-192-maskable.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
client/public/pm/pm-icon-192.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
client/public/pm/pm-icon-512-maskable.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
client/public/pm/pm-icon-512.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
client/public/ro-favicon.png
Normal file
|
After Width: | Height: | Size: 376 B |
@@ -1,53 +1,58 @@
|
||||
import {ApolloProvider} from "@apollo/client";
|
||||
import {SplitFactoryProvider, SplitSdk,} from '@splitsoftware/splitio-react';
|
||||
import {ConfigProvider} from "antd";
|
||||
import { ApolloProvider } from "@apollo/client";
|
||||
import { SplitFactoryProvider, SplitSdk } from "@splitsoftware/splitio-react";
|
||||
import { ConfigProvider } from "antd";
|
||||
import enLocale from "antd/es/locale/en_US";
|
||||
import dayjs from "../utils/day";
|
||||
import 'dayjs/locale/en';
|
||||
import "dayjs/locale/en";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
||||
import client from "../utils/GraphQLClient";
|
||||
import App from "./App";
|
||||
import * as Sentry from "@sentry/react";
|
||||
|
||||
import themeProvider from "./themeProvider";
|
||||
import { Userpilot } from "userpilot";
|
||||
|
||||
// Initialize Userpilot
|
||||
if (import.meta.env.DEV) {
|
||||
Userpilot.initialize("NX-69145f08");
|
||||
}
|
||||
|
||||
dayjs.locale("en");
|
||||
|
||||
const config = {
|
||||
core: {
|
||||
authorizationKey: process.env.REACT_APP_SPLIT_API,
|
||||
key: "anon",
|
||||
},
|
||||
core: {
|
||||
authorizationKey: import.meta.env.VITE_APP_SPLIT_API,
|
||||
key: "anon"
|
||||
}
|
||||
};
|
||||
export const factory = SplitSdk(config);
|
||||
|
||||
|
||||
function AppContainer() {
|
||||
const {t} = useTranslation();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<ConfigProvider
|
||||
//componentSize="small"
|
||||
input={{autoComplete: "new-password"}}
|
||||
locale={enLocale}
|
||||
theme={themeProvider}
|
||||
form={{
|
||||
validateMessages: {
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
required: t("general.validation.required", {label: "${label}"}),
|
||||
},
|
||||
}}
|
||||
>
|
||||
<GlobalLoadingBar/>
|
||||
<SplitFactoryProvider factory={factory}>
|
||||
<App/>
|
||||
</SplitFactoryProvider>
|
||||
</ConfigProvider>
|
||||
</ApolloProvider>
|
||||
);
|
||||
return (
|
||||
<ApolloProvider client={client}>
|
||||
<ConfigProvider
|
||||
//componentSize="small"
|
||||
input={{ autoComplete: "new-password" }}
|
||||
locale={enLocale}
|
||||
theme={themeProvider}
|
||||
form={{
|
||||
validateMessages: {
|
||||
// eslint-disable-next-line no-template-curly-in-string
|
||||
required: t("general.validation.required", { label: "${label}" })
|
||||
}
|
||||
}}
|
||||
>
|
||||
<GlobalLoadingBar />
|
||||
<SplitFactoryProvider factory={factory}>
|
||||
<App />
|
||||
</SplitFactoryProvider>
|
||||
</ConfigProvider>
|
||||
</ApolloProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default Sentry.withProfiler(AppContainer);
|
||||
|
||||
@@ -1,156 +1,231 @@
|
||||
import {useSplitClient} from "@splitsoftware/splitio-react";
|
||||
import {Button, Result} from "antd";
|
||||
import { useSplitClient } from "@splitsoftware/splitio-react";
|
||||
import { Button, Result } from "antd";
|
||||
import LogRocket from "logrocket";
|
||||
import React, {lazy, Suspense, useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {Route, Routes} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import React, { lazy, Suspense, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import DocumentEditorContainer from "../components/document-editor/document-editor.container";
|
||||
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
|
||||
|
||||
//Component Imports
|
||||
import ErrorBoundary from "../components/error-boundary/error-boundary.component"; // Component Imports
|
||||
import LoadingSpinner from "../components/loading-spinner/loading-spinner.component";
|
||||
import DisclaimerPage from "../pages/disclaimer/disclaimer.page";
|
||||
import LandingPage from "../pages/landing/landing.page";
|
||||
import TechPageContainer from "../pages/tech/tech.page.container";
|
||||
import {setOnline} from "../redux/application/application.actions";
|
||||
import {selectOnline} from "../redux/application/application.selectors";
|
||||
import {checkUserSession} from "../redux/user/user.actions";
|
||||
import {selectBodyshop, selectCurrentEula, selectCurrentUser,} from "../redux/user/user.selectors";
|
||||
import { setOnline } from "../redux/application/application.actions";
|
||||
import { selectOnline } from "../redux/application/application.selectors";
|
||||
import { checkUserSession } from "../redux/user/user.actions";
|
||||
import { selectBodyshop, selectCurrentEula, selectCurrentUser } from "../redux/user/user.selectors";
|
||||
import PrivateRoute from "../components/PrivateRoute";
|
||||
import "./App.styles.scss";
|
||||
import handleBeta from "../utils/betaHandler";
|
||||
import Eula from "../components/eula/eula.component";
|
||||
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
||||
import ProductFruitsWrapper from "./ProductFruitsWrapper.jsx";
|
||||
|
||||
const ResetPassword = lazy(() =>
|
||||
import("../pages/reset-password/reset-password.component")
|
||||
);
|
||||
const ResetPassword = lazy(() => import("../pages/reset-password/reset-password.component"));
|
||||
const ManagePage = lazy(() => import("../pages/manage/manage.page.container"));
|
||||
const SignInPage = lazy(() => import("../pages/sign-in/sign-in.page"));
|
||||
|
||||
const CsiPage = lazy(() => import("../pages/csi/csi.container.page"));
|
||||
const MobilePaymentContainer = lazy(() =>
|
||||
import("../pages/mobile-payment/mobile-payment.container")
|
||||
);
|
||||
const MobilePaymentContainer = lazy(() => import("../pages/mobile-payment/mobile-payment.container"));
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
online: selectOnline,
|
||||
bodyshop: selectBodyshop,
|
||||
currentEula: selectCurrentEula
|
||||
currentUser: selectCurrentUser,
|
||||
online: selectOnline,
|
||||
bodyshop: selectBodyshop,
|
||||
currentEula: selectCurrentEula
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
checkUserSession: () => dispatch(checkUserSession()),
|
||||
setOnline: (isOnline) => dispatch(setOnline(isOnline)),
|
||||
checkUserSession: () => dispatch(checkUserSession()),
|
||||
setOnline: (isOnline) => dispatch(setOnline(isOnline))
|
||||
});
|
||||
|
||||
export function App({bodyshop, checkUserSession, currentUser, online, setOnline, currentEula}) {
|
||||
const client = useSplitClient().client;
|
||||
const [listenersAdded, setListenersAdded] = useState(false)
|
||||
const {t} = useTranslation();
|
||||
export function App({ bodyshop, checkUserSession, currentUser, online, setOnline, currentEula }) {
|
||||
const client = useSplitClient().client;
|
||||
const [listenersAdded, setListenersAdded] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!navigator.onLine) {
|
||||
setOnline(false);
|
||||
}
|
||||
|
||||
checkUserSession();
|
||||
}, [checkUserSession, setOnline]);
|
||||
|
||||
//const b = Grid.useBreakpoint();
|
||||
// console.log("Breakpoints:", b);
|
||||
|
||||
// Associate event listeners, memoize to prevent multiple listeners being added
|
||||
useEffect(() => {
|
||||
const offlineListener = (e) => {
|
||||
setOnline(false);
|
||||
}
|
||||
|
||||
const onlineListener = (e) => {
|
||||
setOnline(true);
|
||||
}
|
||||
|
||||
if (!listenersAdded) {
|
||||
console.log('Added events for offline and online');
|
||||
window.addEventListener("offline", offlineListener);
|
||||
window.addEventListener("online", onlineListener);
|
||||
setListenersAdded(true);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("offline", offlineListener);
|
||||
window.removeEventListener("online", onlineListener);
|
||||
}
|
||||
}, [setOnline, listenersAdded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser.authorized && bodyshop) {
|
||||
client.setAttribute("imexshopid", bodyshop.imexshopid);
|
||||
|
||||
if (
|
||||
client.getTreatment("LogRocket_Tracking") === "on" ||
|
||||
window.location.hostname === 'beta.imex.online'
|
||||
) {
|
||||
console.log("LR Start");
|
||||
LogRocket.init("gvfvfw/bodyshopapp");
|
||||
}
|
||||
}
|
||||
}, [bodyshop, client, currentUser.authorized]);
|
||||
|
||||
if (currentUser.authorized === null) {
|
||||
return <LoadingSpinner message={t("general.labels.loggingin")}/>;
|
||||
useEffect(() => {
|
||||
if (!navigator.onLine) {
|
||||
setOnline(false);
|
||||
}
|
||||
|
||||
handleBeta();
|
||||
checkUserSession();
|
||||
}, [checkUserSession, setOnline]);
|
||||
|
||||
if (!online)
|
||||
return (
|
||||
<Result
|
||||
status="warning"
|
||||
title={t("general.labels.nointernet")}
|
||||
subTitle={t("general.labels.nointernet_sub")}
|
||||
extra={
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
window.location.reload();
|
||||
}}
|
||||
>
|
||||
{t("general.actions.refresh")}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
//const b = Grid.useBreakpoint();
|
||||
// console.log("Breakpoints:", b);
|
||||
|
||||
// Associate event listeners, memoize to prevent multiple listeners being added
|
||||
useEffect(() => {
|
||||
const offlineListener = () => {
|
||||
setOnline(false);
|
||||
};
|
||||
|
||||
const onlineListener = () => {
|
||||
setOnline(true);
|
||||
};
|
||||
|
||||
if (!listenersAdded) {
|
||||
console.log("Added events for offline and online");
|
||||
window.addEventListener("offline", offlineListener);
|
||||
window.addEventListener("online", onlineListener);
|
||||
setListenersAdded(true);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("offline", offlineListener);
|
||||
window.removeEventListener("online", onlineListener);
|
||||
};
|
||||
}, [setOnline, listenersAdded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser.authorized && bodyshop) {
|
||||
client.setAttribute("imexshopid", bodyshop.imexshopid);
|
||||
|
||||
if (
|
||||
client.getTreatment("LogRocket_Tracking") === "on" ||
|
||||
window.location.hostname ===
|
||||
InstanceRenderMgr({
|
||||
imex: "beta.imex.online",
|
||||
rome: "beta.romeonline.io"
|
||||
})
|
||||
) {
|
||||
console.log("LR Start");
|
||||
LogRocket.init(
|
||||
InstanceRenderMgr({
|
||||
imex: "gvfvfw/bodyshopapp",
|
||||
rome: "rome-online/rome-online",
|
||||
promanager: "" // TODO: AIO Add in log rocket for promanager instances.
|
||||
})
|
||||
);
|
||||
|
||||
if (currentEula && !currentUser.eulaIsAccepted) {
|
||||
return <Eula/>
|
||||
}
|
||||
}
|
||||
}, [bodyshop, client, currentUser.authorized]);
|
||||
|
||||
// Any route that is not assigned and matched will default to the Landing Page component
|
||||
if (currentUser.authorized === null) {
|
||||
return <LoadingSpinner message={t("general.labels.loggingin")} />;
|
||||
}
|
||||
|
||||
handleBeta();
|
||||
|
||||
if (!online) {
|
||||
return (
|
||||
<Suspense fallback={<LoadingSpinner message="ImEX Online"/>}>
|
||||
<Routes>
|
||||
<Route path="*" element={<ErrorBoundary><LandingPage/></ErrorBoundary>}/>
|
||||
<Route path="/signin" element={<ErrorBoundary><SignInPage/></ErrorBoundary>}/>
|
||||
<Route path="/resetpassword" element={<ErrorBoundary><ResetPassword/></ErrorBoundary>}/>
|
||||
<Route path="/csi/:surveyId" element={<ErrorBoundary><CsiPage/></ErrorBoundary>}/>
|
||||
<Route path="/disclaimer" element={<ErrorBoundary><DisclaimerPage/></ErrorBoundary>}/>
|
||||
<Route path="/mp/:paymentIs" element={<ErrorBoundary><MobilePaymentContainer/></ErrorBoundary>}/>
|
||||
<Route path="/manage/*"
|
||||
element={<ErrorBoundary><PrivateRoute isAuthorized={currentUser.authorized}/></ErrorBoundary>}>
|
||||
<Route path="*" element={<ManagePage/>}/>
|
||||
</Route>
|
||||
<Route path="/tech/*"
|
||||
element={<ErrorBoundary><PrivateRoute isAuthorized={currentUser.authorized}/></ErrorBoundary>}>
|
||||
<Route path="*" element={<TechPageContainer/>}/>
|
||||
</Route>
|
||||
<Route path="/edit/*" element={<PrivateRoute isAuthorized={currentUser.authorized}/>}>
|
||||
<Route path="*" element={<DocumentEditorContainer/>}/>
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
<Result
|
||||
status="warning"
|
||||
title={t("general.labels.nointernet")}
|
||||
subTitle={t("general.labels.nointernet_sub")}
|
||||
extra={
|
||||
<Button type="primary" onClick={() => window.location.reload()}>
|
||||
{t("general.actions.refresh")}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
if (currentEula && !currentUser.eulaIsAccepted) {
|
||||
return <Eula />;
|
||||
}
|
||||
|
||||
// Any route that is not assigned and matched will default to the Landing Page component
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<LoadingSpinner
|
||||
message={InstanceRenderMgr({
|
||||
imex: t("titles.imexonline"),
|
||||
rome: t("titles.romeonline"),
|
||||
promanager: t("titles.promanager")
|
||||
})}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<ProductFruitsWrapper
|
||||
currentUser={currentUser}
|
||||
workspaceCode={InstanceRenderMgr({
|
||||
imex: null,
|
||||
rome: "9BkbEseqNqxw8jUH",
|
||||
promanager: "aoJoEifvezYI0Z0P"
|
||||
})}
|
||||
/>
|
||||
|
||||
<Routes>
|
||||
<Route
|
||||
path="*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<LandingPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/signin"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<SignInPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/resetpassword"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<ResetPassword />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/csi/:surveyId"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<CsiPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/disclaimer"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<DisclaimerPage />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/mp/:paymentIs"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<MobilePaymentContainer />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="/manage/*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute isAuthorized={currentUser.authorized} />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
>
|
||||
<Route path="*" element={<ManagePage />} />
|
||||
</Route>
|
||||
<Route
|
||||
path="/tech/*"
|
||||
element={
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute isAuthorized={currentUser.authorized} />
|
||||
</ErrorBoundary>
|
||||
}
|
||||
>
|
||||
<Route path="*" element={<TechPageContainer />} />
|
||||
</Route>
|
||||
<Route path="/edit/*" element={<PrivateRoute isAuthorized={currentUser.authorized} />}>
|
||||
<Route path="*" element={<DocumentEditorContainer />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(App);
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
.ant-table-tbody > tr.ant-table-row:nth-child(2n) > td {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
@@ -162,3 +161,15 @@
|
||||
.rowWithColor > td {
|
||||
background-color: var(--bgColor) !important;
|
||||
}
|
||||
|
||||
.muted-button {
|
||||
color: lightgray;
|
||||
border: none;
|
||||
background: none;
|
||||
cursor: pointer;
|
||||
font-size: 16px; /* Adjust as needed */
|
||||
}
|
||||
|
||||
.muted-button:hover {
|
||||
color: darkgrey;
|
||||
}
|
||||
|
||||
32
client/src/App/ProductFruitsWrapper.jsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from "react";
|
||||
import { ProductFruits } from "react-product-fruits";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
const ProductFruitsWrapper = React.memo(({ currentUser, workspaceCode }) => {
|
||||
return (
|
||||
workspaceCode &&
|
||||
currentUser?.authorized === true &&
|
||||
currentUser?.email && (
|
||||
<ProductFruits
|
||||
lifeCycle="unmount"
|
||||
workspaceCode={workspaceCode}
|
||||
debug
|
||||
language="en"
|
||||
user={{
|
||||
email: currentUser.email,
|
||||
username: currentUser.email
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
export default ProductFruitsWrapper;
|
||||
|
||||
ProductFruitsWrapper.propTypes = {
|
||||
currentUser: PropTypes.shape({
|
||||
authorized: PropTypes.bool,
|
||||
email: PropTypes.string
|
||||
}),
|
||||
workspaceCode: PropTypes.string
|
||||
};
|
||||
@@ -1,7 +1,8 @@
|
||||
import {defaultsDeep} from "lodash";
|
||||
import {theme} from "antd";
|
||||
import { defaultsDeep } from "lodash";
|
||||
import { theme } from "antd";
|
||||
import InstanceRenderMgr from "../utils/instanceRenderMgr";
|
||||
|
||||
const {defaultAlgorithm, darkAlgorithm} = theme;
|
||||
const { defaultAlgorithm, darkAlgorithm } = theme;
|
||||
|
||||
let isDarkMode = false;
|
||||
|
||||
@@ -10,21 +11,30 @@ let isDarkMode = false;
|
||||
* @type {{components: {Menu: {itemDividerBorderColor: string}}}}
|
||||
*/
|
||||
const defaultTheme = {
|
||||
components: {
|
||||
Table: {
|
||||
rowHoverBg: '#e7f3ff',
|
||||
rowSelectedBg: '#e6f7ff',
|
||||
headerSortHoverBg: 'transparent',
|
||||
},
|
||||
Menu: {
|
||||
darkItemHoverBg: '#1677ff',
|
||||
itemHoverBg: '#1677ff',
|
||||
horizontalItemHoverBg: '#1677ff',
|
||||
}
|
||||
components: {
|
||||
Table: {
|
||||
rowHoverBg: "#e7f3ff",
|
||||
rowSelectedBg: "#e6f7ff",
|
||||
headerSortHoverBg: "transparent"
|
||||
},
|
||||
token: {
|
||||
colorPrimary: '#1677ff'
|
||||
Menu: {
|
||||
darkItemHoverBg: "#1890ff",
|
||||
itemHoverBg: "#1890ff",
|
||||
horizontalItemHoverBg: "#1890ff"
|
||||
}
|
||||
},
|
||||
token: {
|
||||
colorPrimary: InstanceRenderMgr({
|
||||
imex: "#1890ff",
|
||||
rome: "#326ade",
|
||||
promanager: "#1d69a6"
|
||||
}),
|
||||
colorInfo: InstanceRenderMgr({
|
||||
imex: "#1890ff",
|
||||
rome: "#326ade",
|
||||
promanager: "#1d69a6"
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -32,16 +42,16 @@ const defaultTheme = {
|
||||
* @type {{components: {Menu: {itemHoverBg: string, darkItemHoverBg: string, horizontalItemHoverBg: string}}, token: {colorPrimary: string}}}
|
||||
*/
|
||||
const devTheme = {
|
||||
components: {
|
||||
Menu: {
|
||||
darkItemHoverBg: '#a51d1d',
|
||||
itemHoverBg: '#a51d1d',
|
||||
horizontalItemHoverBg: '#a51d1d',
|
||||
}
|
||||
},
|
||||
token: {
|
||||
colorPrimary: '#a51d1d'
|
||||
components: {
|
||||
Menu: {
|
||||
darkItemHoverBg: "#a51d1d",
|
||||
itemHoverBg: "#a51d1d",
|
||||
horizontalItemHoverBg: "#a51d1d"
|
||||
}
|
||||
},
|
||||
token: {
|
||||
colorPrimary: "#a51d1d"
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -50,11 +60,10 @@ const devTheme = {
|
||||
*/
|
||||
const prodTheme = {};
|
||||
|
||||
const currentTheme = process.env.NODE_ENV === "development" ? devTheme
|
||||
: prodTheme;
|
||||
const currentTheme = import.meta.env.DEV ? devTheme : prodTheme;
|
||||
|
||||
const finaltheme = {
|
||||
algorithm: isDarkMode ? darkAlgorithm : defaultAlgorithm,
|
||||
...defaultsDeep(currentTheme, defaultTheme)
|
||||
}
|
||||
export default finaltheme;
|
||||
algorithm: isDarkMode ? darkAlgorithm : defaultAlgorithm,
|
||||
...defaultsDeep(currentTheme, defaultTheme)
|
||||
};
|
||||
export default finaltheme;
|
||||
|
||||
BIN
client/src/assets/RomeOnline.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
BIN
client/src/assets/RomeOnlineBlue.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
client/src/assets/promanager/ProManagerLogo.gif
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
client/src/assets/promanager/android/play_store_512.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@mipmap/ic_launcher_background"/>
|
||||
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||
<monochrome android:drawable="@mipmap/ic_launcher_monochrome"/>
|
||||
</adaptive-icon>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
|
After Width: | Height: | Size: 857 B |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 463 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 10 KiB |