Automation Test Framework

This commit is contained in:
Ankit Hinge
2024-05-07 18:13:51 +05:30
parent dcd7f99510
commit 7324c3df91
24 changed files with 2879 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
pytest = "*"
pytest-html = "*"
pyyaml = "*"
loguru = "*"
selenium = "*"
[dev-packages]
[requires]
python_version = "3.12"
+409
View File
@@ -0,0 +1,409 @@
{
"_meta": {
"hash": {
"sha256": "f77c7c7943f58908fd2ad821aa5c106631c28e6aeaec3e3dfdc163c7a432733f"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.12"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"attrs": {
"hashes": [
"sha256:935dc3b529c262f6cf76e50877d35a4bd3c1de194fd41f47a2b7ae8f19971f30",
"sha256:99b87a485a5820b23b879f04c2305b44b951b502fd64be915879d77a7e8fc6f1"
],
"markers": "python_version >= '3.7'",
"version": "==23.2.0"
},
"certifi": {
"hashes": [
"sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f",
"sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"
],
"markers": "python_version >= '3.6'",
"version": "==2024.2.2"
},
"cffi": {
"hashes": [
"sha256:0c9ef6ff37e974b73c25eecc13952c55bceed9112be2d9d938ded8e856138bcc",
"sha256:131fd094d1065b19540c3d72594260f118b231090295d8c34e19a7bbcf2e860a",
"sha256:1b8ebc27c014c59692bb2664c7d13ce7a6e9a629be20e54e7271fa696ff2b417",
"sha256:2c56b361916f390cd758a57f2e16233eb4f64bcbeee88a4881ea90fca14dc6ab",
"sha256:2d92b25dbf6cae33f65005baf472d2c245c050b1ce709cc4588cdcdd5495b520",
"sha256:31d13b0f99e0836b7ff893d37af07366ebc90b678b6664c955b54561fc36ef36",
"sha256:32c68ef735dbe5857c810328cb2481e24722a59a2003018885514d4c09af9743",
"sha256:3686dffb02459559c74dd3d81748269ffb0eb027c39a6fc99502de37d501faa8",
"sha256:582215a0e9adbe0e379761260553ba11c58943e4bbe9c36430c4ca6ac74b15ed",
"sha256:5b50bf3f55561dac5438f8e70bfcdfd74543fd60df5fa5f62d94e5867deca684",
"sha256:5bf44d66cdf9e893637896c7faa22298baebcd18d1ddb6d2626a6e39793a1d56",
"sha256:6602bc8dc6f3a9e02b6c22c4fc1e47aa50f8f8e6d3f78a5e16ac33ef5fefa324",
"sha256:673739cb539f8cdaa07d92d02efa93c9ccf87e345b9a0b556e3ecc666718468d",
"sha256:68678abf380b42ce21a5f2abde8efee05c114c2fdb2e9eef2efdb0257fba1235",
"sha256:68e7c44931cc171c54ccb702482e9fc723192e88d25a0e133edd7aff8fcd1f6e",
"sha256:6b3d6606d369fc1da4fd8c357d026317fbb9c9b75d36dc16e90e84c26854b088",
"sha256:748dcd1e3d3d7cd5443ef03ce8685043294ad6bd7c02a38d1bd367cfd968e000",
"sha256:7651c50c8c5ef7bdb41108b7b8c5a83013bfaa8a935590c5d74627c047a583c7",
"sha256:7b78010e7b97fef4bee1e896df8a4bbb6712b7f05b7ef630f9d1da00f6444d2e",
"sha256:7e61e3e4fa664a8588aa25c883eab612a188c725755afff6289454d6362b9673",
"sha256:80876338e19c951fdfed6198e70bc88f1c9758b94578d5a7c4c91a87af3cf31c",
"sha256:8895613bcc094d4a1b2dbe179d88d7fb4a15cee43c052e8885783fac397d91fe",
"sha256:88e2b3c14bdb32e440be531ade29d3c50a1a59cd4e51b1dd8b0865c54ea5d2e2",
"sha256:8f8e709127c6c77446a8c0a8c8bf3c8ee706a06cd44b1e827c3e6a2ee6b8c098",
"sha256:9cb4a35b3642fc5c005a6755a5d17c6c8b6bcb6981baf81cea8bfbc8903e8ba8",
"sha256:9f90389693731ff1f659e55c7d1640e2ec43ff725cc61b04b2f9c6d8d017df6a",
"sha256:a09582f178759ee8128d9270cd1344154fd473bb77d94ce0aeb2a93ebf0feaf0",
"sha256:a6a14b17d7e17fa0d207ac08642c8820f84f25ce17a442fd15e27ea18d67c59b",
"sha256:a72e8961a86d19bdb45851d8f1f08b041ea37d2bd8d4fd19903bc3083d80c896",
"sha256:abd808f9c129ba2beda4cfc53bde801e5bcf9d6e0f22f095e45327c038bfe68e",
"sha256:ac0f5edd2360eea2f1daa9e26a41db02dd4b0451b48f7c318e217ee092a213e9",
"sha256:b29ebffcf550f9da55bec9e02ad430c992a87e5f512cd63388abb76f1036d8d2",
"sha256:b2ca4e77f9f47c55c194982e10f058db063937845bb2b7a86c84a6cfe0aefa8b",
"sha256:b7be2d771cdba2942e13215c4e340bfd76398e9227ad10402a8767ab1865d2e6",
"sha256:b84834d0cf97e7d27dd5b7f3aca7b6e9263c56308ab9dc8aae9784abb774d404",
"sha256:b86851a328eedc692acf81fb05444bdf1891747c25af7529e39ddafaf68a4f3f",
"sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0",
"sha256:c0f31130ebc2d37cdd8e44605fb5fa7ad59049298b3f745c74fa74c62fbfcfc4",
"sha256:c6a164aa47843fb1b01e941d385aab7215563bb8816d80ff3a363a9f8448a8dc",
"sha256:d8a9d3ebe49f084ad71f9269834ceccbf398253c9fac910c4fd7053ff1386936",
"sha256:db8e577c19c0fda0beb7e0d4e09e0ba74b1e4c092e0e40bfa12fe05b6f6d75ba",
"sha256:dc9b18bf40cc75f66f40a7379f6a9513244fe33c0e8aa72e2d56b0196a7ef872",
"sha256:e09f3ff613345df5e8c3667da1d918f9149bd623cd9070c983c013792a9a62eb",
"sha256:e4108df7fe9b707191e55f33efbcb2d81928e10cea45527879a4749cbe472614",
"sha256:e6024675e67af929088fda399b2094574609396b1decb609c55fa58b028a32a1",
"sha256:e70f54f1796669ef691ca07d046cd81a29cb4deb1e5f942003f401c0c4a2695d",
"sha256:e715596e683d2ce000574bae5d07bd522c781a822866c20495e52520564f0969",
"sha256:e760191dd42581e023a68b758769e2da259b5d52e3103c6060ddc02c9edb8d7b",
"sha256:ed86a35631f7bfbb28e108dd96773b9d5a6ce4811cf6ea468bb6a359b256b1e4",
"sha256:ee07e47c12890ef248766a6e55bd38ebfb2bb8edd4142d56db91b21ea68b7627",
"sha256:fa3a0128b152627161ce47201262d3140edb5a5c3da88d73a1b790a959126956",
"sha256:fcc8eb6d5902bb1cf6dc4f187ee3ea80a1eba0a89aba40a5cb20a5087d961357"
],
"markers": "os_name == 'nt' and implementation_name != 'pypy'",
"version": "==1.16.0"
},
"colorama": {
"hashes": [
"sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44",
"sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"
],
"markers": "sys_platform == 'win32'",
"version": "==0.4.6"
},
"h11": {
"hashes": [
"sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d",
"sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"
],
"markers": "python_version >= '3.7'",
"version": "==0.14.0"
},
"idna": {
"hashes": [
"sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc",
"sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"
],
"markers": "python_version >= '3.5'",
"version": "==3.7"
},
"iniconfig": {
"hashes": [
"sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3",
"sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"
],
"markers": "python_version >= '3.7'",
"version": "==2.0.0"
},
"jinja2": {
"hashes": [
"sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
"sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
],
"markers": "python_version >= '3.7'",
"version": "==3.1.4"
},
"loguru": {
"hashes": [
"sha256:003d71e3d3ed35f0f8984898359d65b79e5b21943f78af86aa5491210429b8eb",
"sha256:e671a53522515f34fd406340ee968cb9ecafbc4b36c679da03c18fd8d0bd51ac"
],
"index": "pypi",
"markers": "python_version >= '3.5'",
"version": "==0.7.2"
},
"markupsafe": {
"hashes": [
"sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf",
"sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff",
"sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f",
"sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3",
"sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532",
"sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f",
"sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617",
"sha256:2d2d793e36e230fd32babe143b04cec8a8b3eb8a3122d2aceb4a371e6b09b8df",
"sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4",
"sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906",
"sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f",
"sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4",
"sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8",
"sha256:4096e9de5c6fdf43fb4f04c26fb114f61ef0bf2e5604b6ee3019d51b69e8c371",
"sha256:4275d846e41ecefa46e2015117a9f491e57a71ddd59bbead77e904dc02b1bed2",
"sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465",
"sha256:4f11aa001c540f62c6166c7726f71f7573b52c68c31f014c25cc7901deea0b52",
"sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6",
"sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169",
"sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad",
"sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2",
"sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0",
"sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029",
"sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f",
"sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a",
"sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced",
"sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5",
"sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c",
"sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf",
"sha256:7b2e5a267c855eea6b4283940daa6e88a285f5f2a67f2220203786dfa59b37e9",
"sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb",
"sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad",
"sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3",
"sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1",
"sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46",
"sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc",
"sha256:a549b9c31bec33820e885335b451286e2969a2d9e24879f83fe904a5ce59d70a",
"sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee",
"sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900",
"sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5",
"sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea",
"sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f",
"sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5",
"sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e",
"sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a",
"sha256:c8b29db45f8fe46ad280a7294f5c3ec36dbac9491f2d1c17345be8e69cc5928f",
"sha256:ce409136744f6521e39fd8e2a24c53fa18ad67aa5bc7c2cf83645cce5b5c4e50",
"sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a",
"sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b",
"sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4",
"sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff",
"sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2",
"sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46",
"sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b",
"sha256:ec6a563cff360b50eed26f13adc43e61bc0c04d94b8be985e6fb24b81f6dcfdf",
"sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5",
"sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5",
"sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab",
"sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd",
"sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68"
],
"markers": "python_version >= '3.7'",
"version": "==2.1.5"
},
"outcome": {
"hashes": [
"sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8",
"sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b"
],
"markers": "python_version >= '3.7'",
"version": "==1.3.0.post0"
},
"packaging": {
"hashes": [
"sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
"sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"
],
"markers": "python_version >= '3.7'",
"version": "==24.0"
},
"pluggy": {
"hashes": [
"sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1",
"sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"
],
"markers": "python_version >= '3.8'",
"version": "==1.5.0"
},
"pycparser": {
"hashes": [
"sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6",
"sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"
],
"markers": "python_version >= '3.8'",
"version": "==2.22"
},
"pysocks": {
"hashes": [
"sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299",
"sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5",
"sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0"
],
"version": "==1.7.1"
},
"pytest": {
"hashes": [
"sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233",
"sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==8.2.0"
},
"pytest-html": {
"hashes": [
"sha256:70a01e8ae5800f4a074b56a4cb1025c8f4f9b038bba5fe31e3c98eb996686f07",
"sha256:c8152cea03bd4e9bee6d525573b67bbc6622967b72b9628dda0ea3e2a0b5dd71"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==4.1.1"
},
"pytest-metadata": {
"hashes": [
"sha256:c8e0844db684ee1c798cfa38908d20d67d0463ecb6137c72e91f418558dd5f4b",
"sha256:d2a29b0355fbc03f168aa96d41ff88b1a3b44a3b02acbe491801c98a048017c8"
],
"markers": "python_version >= '3.8'",
"version": "==3.1.1"
},
"pyyaml": {
"hashes": [
"sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5",
"sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc",
"sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df",
"sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741",
"sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206",
"sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27",
"sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595",
"sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62",
"sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98",
"sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696",
"sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290",
"sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9",
"sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d",
"sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6",
"sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867",
"sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47",
"sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486",
"sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6",
"sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3",
"sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007",
"sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938",
"sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0",
"sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c",
"sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735",
"sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d",
"sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28",
"sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4",
"sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba",
"sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8",
"sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef",
"sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5",
"sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd",
"sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3",
"sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0",
"sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515",
"sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c",
"sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c",
"sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924",
"sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34",
"sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43",
"sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859",
"sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673",
"sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54",
"sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a",
"sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b",
"sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab",
"sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa",
"sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c",
"sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585",
"sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d",
"sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"
],
"index": "pypi",
"markers": "python_version >= '3.6'",
"version": "==6.0.1"
},
"selenium": {
"hashes": [
"sha256:0bd564ee166980d419a8aaf4ac00289bc152afcf2eadca5efe8c8e36711853fd",
"sha256:b1d0c33b38ca27d0499183e48e1dd09ff26973481f5d3ef2983073813ae6588d"
],
"index": "pypi",
"markers": "python_version >= '3.8'",
"version": "==4.20.0"
},
"sniffio": {
"hashes": [
"sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2",
"sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"
],
"markers": "python_version >= '3.7'",
"version": "==1.3.1"
},
"sortedcontainers": {
"hashes": [
"sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88",
"sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0"
],
"version": "==2.4.0"
},
"trio": {
"hashes": [
"sha256:9b41f5993ad2c0e5f62d0acca320ec657fdb6b2a2c22b8c7aed6caf154475c4e",
"sha256:e6458efe29cc543e557a91e614e2b51710eba2961669329ce9c862d50c6e8e81"
],
"markers": "python_version >= '3.8'",
"version": "==0.25.0"
},
"trio-websocket": {
"hashes": [
"sha256:18c11793647703c158b1f6e62de638acada927344d534e3c7628eedcb746839f",
"sha256:520d046b0d030cf970b8b2b2e00c4c2245b3807853ecd44214acd33d74581638"
],
"markers": "python_version >= '3.7'",
"version": "==0.11.1"
},
"typing-extensions": {
"hashes": [
"sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0",
"sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"
],
"markers": "python_version >= '3.8'",
"version": "==4.11.0"
},
"urllib3": {
"extras": [
"socks"
],
"hashes": [
"sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d",
"sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"
],
"markers": "python_version >= '3.8'",
"version": "==2.2.1"
},
"win32-setctime": {
"hashes": [
"sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2",
"sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"
],
"markers": "sys_platform == 'win32'",
"version": "==1.1.0"
},
"wsproto": {
"hashes": [
"sha256:ad565f26ecb92588a3e43bc3d96164de84cd9902482b130d0ddbaa9664a85065",
"sha256:b9acddd652b585d75b20477888c56642fdade28bdfd3579aa24a4d2c037dd736"
],
"markers": "python_full_version >= '3.7.0'",
"version": "==1.2.0"
}
},
"develop": {}
}
+4
View File
@@ -0,0 +1,4 @@
environment:
url: "https://doczy.aarete.com:8500/"
username: "ahinge@aarete.com"
password: "7387188738@Pr!nce"
@@ -0,0 +1,20 @@
from selenium.webdriver.common.by import By
from utils.common_methods import get_element, get_clickable_element
class Email_sign_in_page:
def __init__(self, driver):
self.driver = driver
self.email = get_element(self.driver, By.NAME, 'loginfmt')
self.next_btn = get_clickable_element(self.driver, By.ID, "idSIButton9")
def set_email(self, email):
self.email.clear()
self.email.send_keys(email)
def click_next_btn(self):
self.next_btn.click()
def sign_in(self, config):
self.set_email(config['username'])
self.click_next_btn()
@@ -0,0 +1,21 @@
from selenium.webdriver.common.by import By
from utils.common_methods import get_clickable_element, get_element
class Password_sign_in_page:
def __init__(self, driver):
self.driver = driver
self.password = get_element(self.driver, By.NAME, 'passwd')
self.sign_in_btn = get_clickable_element(self.driver, By.ID, 'idSIButton9')
def set_password(self, password):
self.password.clear()
self.password.send_keys(password)
def click_sign_in_btn(self):
self.sign_in_btn.click()
def sign_in(self, config):
self.set_password(config['password'])
self.click_sign_in_btn()
@@ -0,0 +1,14 @@
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from utils.common_methods import get_clickable_element
class Pre_sign_in_page:
def __init__(self, driver):
self.driver = driver
self.sign_in = get_clickable_element(self.driver, By.TAG_NAME, 'a')
def click_sign_in_link(self):
self.sign_in.click()
@@ -0,0 +1,13 @@
from selenium.webdriver.common.by import By
from utils.common_methods import get_clickable_element
class Remember_sign_in_page:
def __init__(self, driver):
self.driver = driver
self.no_btn = get_clickable_element(self.driver, By.ID, 'idBtn_Back')
self.yes_btn = get_clickable_element(self.driver, By.ID, 'idSIButton9')
def click_no_btn(self):
self.no_btn.click()
@@ -0,0 +1,82 @@
# pages/your_page_objects.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
class Interface_0:
def __init__(self, driver):
self.driver = driver
# self.driver.get(url)
self.sign_in = self.get_clickable_element(By.TAG_NAME, 'a')
self.email = self.get_element(By.NAME, 'loginfmt')
self.next_btn = self.get_clickable_element(By.ID,"idSIButton9")
self.password = self.get_element(By.NAME, 'passwd')
self.sign_in_btn = self.get_clickable_element(By.ID, 'idSIButton9')
# "idBtn_Back"
# "idSIButton9"
def set_email(self,email):
self.email.clear()
self.email.send_keys(email)
def set_password(self, password):
self.password.clear()
self.password.send_keys(password)
def click_sign_in_link(self):
self.sign_in.click()
def click_next_btn(self):
self.next_btn.click()
def click_sign_in_btn(self):
self.sign_in_btn.click()
def navigate_to_page(self, url):
self.driver.get(url)
def sign_in(self, env_variables):
self.click_sign_in_link()
self.set_email(env_variables['username'])
self.click_next_btn()
self.set_password(env_variables['password'])
self.click_sign_in_btn()
self.title()
# print(env_variables['username'])
#
# sign_in = self.get_clickable_element(By.TAG_NAME, "a")
# sign_in.click()
#
# email = self.get_element(By.NAME, 'loginfmt')
# email.send_keys('ahinge@aarete.com')
#
# next_btn = self.get_clickable_element(By.ID,"idSIButton9")
# next_btn.click()
#
# password = self.get_element(By.NAME, 'passwd')
# password.send_keys('7387188738@Pr!nce')
#
# next_btn1 = self.get_clickable_element(By.ID, 'idSIButton9')
# next_btn1.click()
#
# self.title()
def title(self):
self.get_title("interface_0 · Streamlit")
def get_clickable_element(self, By, element_id):
return WebDriverWait(self.driver, timeout=10).until(
ec.element_to_be_clickable((By, element_id))
)
def get_element(self, By, element_id):
return WebDriverWait(self.driver, timeout=10).until(
ec.visibility_of_element_located((By, element_id))
)
def get_title(self, title):
return WebDriverWait(self.driver, timeout=50).until(
ec.title_contains(title)
)
+2
View File
@@ -0,0 +1,2 @@
[pytest]
addopts = --html=reports/test_report.html
@@ -0,0 +1,319 @@
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
/* do not increase min-width as some may use split screens */
min-width: 800px;
color: #999;
}
h1 {
font-size: 24px;
color: black;
}
h2 {
font-size: 16px;
color: black;
}
p {
color: black;
}
a {
color: #999;
}
table {
border-collapse: collapse;
}
/******************************
* SUMMARY INFORMATION
******************************/
#environment td {
padding: 5px;
border: 1px solid #e6e6e6;
vertical-align: top;
}
#environment tr:nth-child(odd) {
background-color: #f6f6f6;
}
#environment ul {
margin: 0;
padding: 0 20px;
}
/******************************
* TEST RESULT COLORS
******************************/
span.passed,
.passed .col-result {
color: green;
}
span.skipped,
span.xfailed,
span.rerun,
.skipped .col-result,
.xfailed .col-result,
.rerun .col-result {
color: orange;
}
span.error,
span.failed,
span.xpassed,
.error .col-result,
.failed .col-result,
.xpassed .col-result {
color: red;
}
.col-links__extra {
margin-right: 3px;
}
/******************************
* RESULTS TABLE
*
* 1. Table Layout
* 2. Extra
* 3. Sorting items
*
******************************/
/*------------------
* 1. Table Layout
*------------------*/
#results-table {
border: 1px solid #e6e6e6;
color: #999;
font-size: 12px;
width: 100%;
}
#results-table th,
#results-table td {
padding: 5px;
border: 1px solid #e6e6e6;
text-align: left;
}
#results-table th {
font-weight: bold;
}
/*------------------
* 2. Extra
*------------------*/
.logwrapper {
max-height: 230px;
overflow-y: scroll;
background-color: #e6e6e6;
}
.logwrapper.expanded {
max-height: none;
}
.logwrapper.expanded .logexpander:after {
content: "collapse [-]";
}
.logwrapper .logexpander {
z-index: 1;
position: sticky;
top: 10px;
width: max-content;
border: 1px solid;
border-radius: 3px;
padding: 5px 7px;
margin: 10px 0 10px calc(100% - 80px);
cursor: pointer;
background-color: #e6e6e6;
}
.logwrapper .logexpander:after {
content: "expand [+]";
}
.logwrapper .logexpander:hover {
color: #000;
border-color: #000;
}
.logwrapper .log {
min-height: 40px;
position: relative;
top: -50px;
height: calc(100% + 50px);
border: 1px solid #e6e6e6;
color: black;
display: block;
font-family: "Courier New", Courier, monospace;
padding: 5px;
padding-right: 80px;
white-space: pre-wrap;
}
div.media {
border: 1px solid #e6e6e6;
float: right;
height: 240px;
margin: 0 5px;
overflow: hidden;
width: 320px;
}
.media-container {
display: grid;
grid-template-columns: 25px auto 25px;
align-items: center;
flex: 1 1;
overflow: hidden;
height: 200px;
}
.media-container--fullscreen {
grid-template-columns: 0px auto 0px;
}
.media-container__nav--right,
.media-container__nav--left {
text-align: center;
cursor: pointer;
}
.media-container__viewport {
cursor: pointer;
text-align: center;
height: inherit;
}
.media-container__viewport img,
.media-container__viewport video {
object-fit: cover;
width: 100%;
max-height: 100%;
}
.media__name,
.media__counter {
display: flex;
flex-direction: row;
justify-content: space-around;
flex: 0 0 25px;
align-items: center;
}
.collapsible td:not(.col-links) {
cursor: pointer;
}
.collapsible td:not(.col-links):hover::after {
color: #bbb;
font-style: italic;
cursor: pointer;
}
.col-result {
width: 130px;
}
.col-result:hover::after {
content: " (hide details)";
}
.col-result.collapsed:hover::after {
content: " (show details)";
}
#environment-header h2:hover::after {
content: " (hide details)";
color: #bbb;
font-style: italic;
cursor: pointer;
font-size: 12px;
}
#environment-header.collapsed h2:hover::after {
content: " (show details)";
color: #bbb;
font-style: italic;
cursor: pointer;
font-size: 12px;
}
/*------------------
* 3. Sorting items
*------------------*/
.sortable {
cursor: pointer;
}
.sortable.desc:after {
content: " ";
position: relative;
left: 5px;
bottom: -12.5px;
border: 10px solid #4caf50;
border-bottom: 0;
border-left-color: transparent;
border-right-color: transparent;
}
.sortable.asc:after {
content: " ";
position: relative;
left: 5px;
bottom: 12.5px;
border: 10px solid #4caf50;
border-top: 0;
border-left-color: transparent;
border-right-color: transparent;
}
.hidden, .summary__reload__button.hidden {
display: none;
}
.summary__data {
flex: 0 0 550px;
}
.summary__reload {
flex: 1 1;
display: flex;
justify-content: center;
}
.summary__reload__button {
flex: 0 0 300px;
display: flex;
color: white;
font-weight: bold;
background-color: #4caf50;
text-align: center;
justify-content: center;
align-items: center;
border-radius: 3px;
cursor: pointer;
}
.summary__reload__button:hover {
background-color: #46a049;
}
.summary__spacer {
flex: 0 0 550px;
}
.controls {
display: flex;
justify-content: space-between;
}
.filters,
.collapse {
display: flex;
align-items: center;
}
.filters button,
.collapse button {
color: #999;
border: none;
background: none;
cursor: pointer;
text-decoration: underline;
}
.filters button:hover,
.collapse button:hover {
color: #ccc;
}
.filter__label {
margin-right: 10px;
}
@@ -0,0 +1,770 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title id="head-title">test_report.html</title>
<link href="assets\style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<h1 id="title">test_report.html</h1>
<p>Report generated on 07-May-2024 at 17:37:48 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
v4.1.1</p>
<div id="environment-header">
<h2>Environment</h2>
</div>
<table id="environment"></table>
<!-- TEMPLATES -->
<template id="template_environment_row">
<tr>
<td></td>
<td></td>
</tr>
</template>
<template id="template_results-table__body--empty">
<tbody class="results-table-row">
<tr id="not-found-message">
<td colspan="4">No results found. Check the filters.</th>
</tr>
</template>
<template id="template_results-table__tbody">
<tbody class="results-table-row">
<tr class="collapsible">
</tr>
<tr class="extras-row">
<td class="extra" colspan="4">
<div class="extraHTML"></div>
<div class="media">
<div class="media-container">
<div class="media-container__nav--left"><</div>
<div class="media-container__viewport">
<img src="" />
<video controls>
<source src="" type="video/mp4">
</video>
</div>
<div class="media-container__nav--right">></div>
</div>
<div class="media__name"></div>
<div class="media__counter"></div>
</div>
<div class="logwrapper">
<div class="logexpander"></div>
<div class="log"></div>
</div>
</td>
</tr>
</tbody>
</template>
<!-- END TEMPLATES -->
<div class="summary">
<div class="summary__data">
<h2>Summary</h2>
<div class="additional-summary prefix">
</div>
<p class="run-count">2 tests took 00:01:20.</p>
<p class="filter">(Un)check the boxes to filter the results.</p>
<div class="summary__reload">
<div class="summary__reload__button hidden" onclick="location.reload()">
<div>There are still tests running. <br />Reload this page to get the latest results!</div>
</div>
</div>
<div class="summary__spacer"></div>
<div class="controls">
<div class="filters">
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="failed" disabled/>
<span class="failed">0 Failed,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="passed" />
<span class="passed">2 Passed,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="skipped" disabled/>
<span class="skipped">0 Skipped,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xfailed" disabled/>
<span class="xfailed">0 Expected failures,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xpassed" disabled/>
<span class="xpassed">0 Unexpected passes,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="error" disabled/>
<span class="error">0 Errors,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="rerun" disabled/>
<span class="rerun">0 Reruns</span>
</div>
<div class="collapse">
<button id="show_all_details">Show all details</button>&nbsp;/&nbsp;<button id="hide_all_details">Hide all details</button>
</div>
</div>
</div>
<div class="additional-summary summary">
</div>
<div class="additional-summary postfix">
</div>
</div>
<table id="results-table">
<thead id="results-table-head">
<tr>
<th class="sortable" data-column-type="result">Result</th>
<th class="sortable" data-column-type="testId">Test</th>
<th class="sortable" data-column-type="duration">Duration</th>
<th>Links</th>
</tr>
</thead>
</table>
</body>
<footer>
<div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.12.3&#34;, &#34;Platform&#34;: &#34;Windows-10-10.0.19045-SP0&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.2.0&#34;, &#34;pluggy&#34;: &#34;1.5.0&#34;}, &#34;Plugins&#34;: {&#34;html&#34;: &#34;4.1.1&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;}}, &#34;tests&#34;: {&#34;tests/test_interface_0.py::Test_interface_0::test_validate_navigation&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Passed&#34;, &#34;testId&#34;: &#34;tests/test_interface_0.py::Test_interface_0::test_validate_navigation&#34;, &#34;duration&#34;: &#34;00:00:09&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Passed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;tests/test_interface_0.py::Test_interface_0::test_validate_navigation&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:00:09&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;----------------------------- Captured stderr call -----------------------------\n2024-05-07 17:36:22.158 | INFO | tests.test_interface_0:test_validate_navigation:11 - Opening URL https://doczy.aarete.com:8500/\n2024-05-07 17:36:25.930 | INFO | tests.test_interface_0:test_validate_navigation:13 - URL https://doczy.aarete.com:8500/ opened\n&#34;}], &#34;tests/test_interface_0.py::Test_interface_0::test_interface_0&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Passed&#34;, &#34;testId&#34;: &#34;tests/test_interface_0.py::Test_interface_0::test_interface_0&#34;, &#34;duration&#34;: &#34;00:01:10&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Passed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;tests/test_interface_0.py::Test_interface_0::test_interface_0&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:01:10&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;----------------------------- Captured stderr call -----------------------------\n2024-05-07 17:36:35.639 | INFO | tests.test_interface_0:test_interface_0:21 - Opening URL https://doczy.aarete.com:8500/\n2024-05-07 17:36:39.603 | INFO | tests.test_interface_0:test_interface_0:23 - URL https://doczy.aarete.com:8500/ opened\n2024-05-07 17:36:44.694 | INFO | utils.common_methods2:sign_in:13 - Adding email\n2024-05-07 17:36:48.518 | INFO | utils.common_methods2:sign_in:16 - Email added\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;test_report.html&#34;}"></div>
<script>
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const { getCollapsedCategory, setCollapsedIds } = require('./storage.js')
class DataManager {
setManager(data) {
const collapsedCategories = [...getCollapsedCategory(data.renderCollapsed)]
const collapsedIds = []
const tests = Object.values(data.tests).flat().map((test, index) => {
const collapsed = collapsedCategories.includes(test.result.toLowerCase())
const id = `test_${index}`
if (collapsed) {
collapsedIds.push(id)
}
return {
...test,
id,
collapsed,
}
})
const dataBlob = { ...data, tests }
this.data = { ...dataBlob }
this.renderData = { ...dataBlob }
setCollapsedIds(collapsedIds)
}
get allData() {
return { ...this.data }
}
resetRender() {
this.renderData = { ...this.data }
}
setRender(data) {
this.renderData.tests = [...data]
}
toggleCollapsedItem(id) {
this.renderData.tests = this.renderData.tests.map((test) =>
test.id === id ? { ...test, collapsed: !test.collapsed } : test,
)
}
set allCollapsed(collapsed) {
this.renderData = { ...this.renderData, tests: [...this.renderData.tests.map((test) => (
{ ...test, collapsed }
))] }
}
get testSubset() {
return [...this.renderData.tests]
}
get environment() {
return this.renderData.environment
}
get initialSort() {
return this.data.initialSort
}
}
module.exports = {
manager: new DataManager(),
}
},{"./storage.js":8}],2:[function(require,module,exports){
const mediaViewer = require('./mediaviewer.js')
const templateEnvRow = document.getElementById('template_environment_row')
const templateResult = document.getElementById('template_results-table__tbody')
function htmlToElements(html) {
const temp = document.createElement('template')
temp.innerHTML = html
return temp.content.childNodes
}
const find = (selector, elem) => {
if (!elem) {
elem = document
}
return elem.querySelector(selector)
}
const findAll = (selector, elem) => {
if (!elem) {
elem = document
}
return [...elem.querySelectorAll(selector)]
}
const dom = {
getStaticRow: (key, value) => {
const envRow = templateEnvRow.content.cloneNode(true)
const isObj = typeof value === 'object' && value !== null
const values = isObj ? Object.keys(value).map((k) => `${k}: ${value[k]}`) : null
const valuesElement = htmlToElements(
values ? `<ul>${values.map((val) => `<li>${val}</li>`).join('')}<ul>` : `<div>${value}</div>`)[0]
const td = findAll('td', envRow)
td[0].textContent = key
td[1].appendChild(valuesElement)
return envRow
},
getResultTBody: ({ testId, id, log, extras, resultsTableRow, tableHtml, result, collapsed }) => {
const resultBody = templateResult.content.cloneNode(true)
resultBody.querySelector('tbody').classList.add(result.toLowerCase())
resultBody.querySelector('tbody').id = testId
resultBody.querySelector('.collapsible').dataset.id = id
resultsTableRow.forEach((html) => {
const t = document.createElement('template')
t.innerHTML = html
resultBody.querySelector('.collapsible').appendChild(t.content)
})
if (log) {
// Wrap lines starting with "E" with span.error to color those lines red
const wrappedLog = log.replace(/^E.*$/gm, (match) => `<span class="error">${match}</span>`)
resultBody.querySelector('.log').innerHTML = wrappedLog
} else {
resultBody.querySelector('.log').remove()
}
if (collapsed) {
resultBody.querySelector('.collapsible > td')?.classList.add('collapsed')
resultBody.querySelector('.extras-row').classList.add('hidden')
} else {
resultBody.querySelector('.collapsible > td')?.classList.remove('collapsed')
}
const media = []
extras?.forEach(({ name, format_type, content }) => {
if (['image', 'video'].includes(format_type)) {
media.push({ path: content, name, format_type })
}
if (format_type === 'html') {
resultBody.querySelector('.extraHTML').insertAdjacentHTML('beforeend', `<div>${content}</div>`)
}
})
mediaViewer.setup(resultBody, media)
// Add custom html from the pytest_html_results_table_html hook
tableHtml?.forEach((item) => {
resultBody.querySelector('td[class="extra"]').insertAdjacentHTML('beforeend', item)
})
return resultBody
},
}
module.exports = {
dom,
htmlToElements,
find,
findAll,
}
},{"./mediaviewer.js":6}],3:[function(require,module,exports){
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const storageModule = require('./storage.js')
const getFilteredSubSet = (filter) =>
manager.allData.tests.filter(({ result }) => filter.includes(result.toLowerCase()))
const doInitFilter = () => {
const currentFilter = storageModule.getVisible()
const filteredSubset = getFilteredSubSet(currentFilter)
manager.setRender(filteredSubset)
}
const doFilter = (type, show) => {
if (show) {
storageModule.showCategory(type)
} else {
storageModule.hideCategory(type)
}
const currentFilter = storageModule.getVisible()
const filteredSubset = getFilteredSubSet(currentFilter)
manager.setRender(filteredSubset)
const sortColumn = storageModule.getSort()
doSort(sortColumn, true)
}
module.exports = {
doFilter,
doInitFilter,
}
},{"./datamanager.js":1,"./sort.js":7,"./storage.js":8}],4:[function(require,module,exports){
const { redraw, bindEvents, renderStatic } = require('./main.js')
const { doInitFilter } = require('./filter.js')
const { doInitSort } = require('./sort.js')
const { manager } = require('./datamanager.js')
const data = JSON.parse(document.getElementById('data-container').dataset.jsonblob)
function init() {
manager.setManager(data)
doInitFilter()
doInitSort()
renderStatic()
redraw()
bindEvents()
}
init()
},{"./datamanager.js":1,"./filter.js":3,"./main.js":5,"./sort.js":7}],5:[function(require,module,exports){
const { dom, find, findAll } = require('./dom.js')
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const { doFilter } = require('./filter.js')
const {
getVisible,
getCollapsedIds,
setCollapsedIds,
getSort,
getSortDirection,
possibleFilters,
} = require('./storage.js')
const removeChildren = (node) => {
while (node.firstChild) {
node.removeChild(node.firstChild)
}
}
const renderStatic = () => {
const renderEnvironmentTable = () => {
const environment = manager.environment
const rows = Object.keys(environment).map((key) => dom.getStaticRow(key, environment[key]))
const table = document.getElementById('environment')
removeChildren(table)
rows.forEach((row) => table.appendChild(row))
}
renderEnvironmentTable()
}
const addItemToggleListener = (elem) => {
elem.addEventListener('click', ({ target }) => {
const id = target.parentElement.dataset.id
manager.toggleCollapsedItem(id)
const collapsedIds = getCollapsedIds()
if (collapsedIds.includes(id)) {
const updated = collapsedIds.filter((item) => item !== id)
setCollapsedIds(updated)
} else {
collapsedIds.push(id)
setCollapsedIds(collapsedIds)
}
redraw()
})
}
const renderContent = (tests) => {
const sortAttr = getSort(manager.initialSort)
const sortAsc = JSON.parse(getSortDirection())
const rows = tests.map(dom.getResultTBody)
const table = document.getElementById('results-table')
const tableHeader = document.getElementById('results-table-head')
const newTable = document.createElement('table')
newTable.id = 'results-table'
// remove all sorting classes and set the relevant
findAll('.sortable', tableHeader).forEach((elem) => elem.classList.remove('asc', 'desc'))
tableHeader.querySelector(`.sortable[data-column-type="${sortAttr}"]`)?.classList.add(sortAsc ? 'desc' : 'asc')
newTable.appendChild(tableHeader)
if (!rows.length) {
const emptyTable = document.getElementById('template_results-table__body--empty').content.cloneNode(true)
newTable.appendChild(emptyTable)
} else {
rows.forEach((row) => {
if (!!row) {
findAll('.collapsible td:not(.col-links', row).forEach(addItemToggleListener)
find('.logexpander', row).addEventListener('click',
(evt) => evt.target.parentNode.classList.toggle('expanded'),
)
newTable.appendChild(row)
}
})
}
table.replaceWith(newTable)
}
const renderDerived = () => {
const currentFilter = getVisible()
possibleFilters.forEach((result) => {
const input = document.querySelector(`input[data-test-result="${result}"]`)
input.checked = currentFilter.includes(result)
})
}
const bindEvents = () => {
const filterColumn = (evt) => {
const { target: element } = evt
const { testResult } = element.dataset
doFilter(testResult, element.checked)
const collapsedIds = getCollapsedIds()
const updated = manager.renderData.tests.map((test) => {
return {
...test,
collapsed: collapsedIds.includes(test.id),
}
})
manager.setRender(updated)
redraw()
}
const header = document.getElementById('environment-header')
header.addEventListener('click', () => {
const table = document.getElementById('environment')
table.classList.toggle('hidden')
header.classList.toggle('collapsed')
})
findAll('input[name="filter_checkbox"]').forEach((elem) => {
elem.addEventListener('click', filterColumn)
})
findAll('.sortable').forEach((elem) => {
elem.addEventListener('click', (evt) => {
const { target: element } = evt
const { columnType } = element.dataset
doSort(columnType)
redraw()
})
})
document.getElementById('show_all_details').addEventListener('click', () => {
manager.allCollapsed = false
setCollapsedIds([])
redraw()
})
document.getElementById('hide_all_details').addEventListener('click', () => {
manager.allCollapsed = true
const allIds = manager.renderData.tests.map((test) => test.id)
setCollapsedIds(allIds)
redraw()
})
}
const redraw = () => {
const { testSubset } = manager
renderContent(testSubset)
renderDerived()
}
module.exports = {
redraw,
bindEvents,
renderStatic,
}
},{"./datamanager.js":1,"./dom.js":2,"./filter.js":3,"./sort.js":7,"./storage.js":8}],6:[function(require,module,exports){
class MediaViewer {
constructor(assets) {
this.assets = assets
this.index = 0
}
nextActive() {
this.index = this.index === this.assets.length - 1 ? 0 : this.index + 1
return [this.activeFile, this.index]
}
prevActive() {
this.index = this.index === 0 ? this.assets.length - 1 : this.index -1
return [this.activeFile, this.index]
}
get currentIndex() {
return this.index
}
get activeFile() {
return this.assets[this.index]
}
}
const setup = (resultBody, assets) => {
if (!assets.length) {
resultBody.querySelector('.media').classList.add('hidden')
return
}
const mediaViewer = new MediaViewer(assets)
const container = resultBody.querySelector('.media-container')
const leftArrow = resultBody.querySelector('.media-container__nav--left')
const rightArrow = resultBody.querySelector('.media-container__nav--right')
const mediaName = resultBody.querySelector('.media__name')
const counter = resultBody.querySelector('.media__counter')
const imageEl = resultBody.querySelector('img')
const sourceEl = resultBody.querySelector('source')
const videoEl = resultBody.querySelector('video')
const setImg = (media, index) => {
if (media?.format_type === 'image') {
imageEl.src = media.path
imageEl.classList.remove('hidden')
videoEl.classList.add('hidden')
} else if (media?.format_type === 'video') {
sourceEl.src = media.path
videoEl.classList.remove('hidden')
imageEl.classList.add('hidden')
}
mediaName.innerText = media?.name
counter.innerText = `${index + 1} / ${assets.length}`
}
setImg(mediaViewer.activeFile, mediaViewer.currentIndex)
const moveLeft = () => {
const [media, index] = mediaViewer.prevActive()
setImg(media, index)
}
const doRight = () => {
const [media, index] = mediaViewer.nextActive()
setImg(media, index)
}
const openImg = () => {
window.open(mediaViewer.activeFile.path, '_blank')
}
if (assets.length === 1) {
container.classList.add('media-container--fullscreen')
} else {
leftArrow.addEventListener('click', moveLeft)
rightArrow.addEventListener('click', doRight)
}
imageEl.addEventListener('click', openImg)
}
module.exports = {
setup,
}
},{}],7:[function(require,module,exports){
const { manager } = require('./datamanager.js')
const storageModule = require('./storage.js')
const genericSort = (list, key, ascending, customOrder) => {
let sorted
if (customOrder) {
sorted = list.sort((a, b) => {
const aValue = a.result.toLowerCase()
const bValue = b.result.toLowerCase()
const aIndex = customOrder.findIndex((item) => item.toLowerCase() === aValue)
const bIndex = customOrder.findIndex((item) => item.toLowerCase() === bValue)
// Compare the indices to determine the sort order
return aIndex - bIndex
})
} else {
sorted = list.sort((a, b) => a[key] === b[key] ? 0 : a[key] > b[key] ? 1 : -1)
}
if (ascending) {
sorted.reverse()
}
return sorted
}
const durationSort = (list, ascending) => {
const parseDuration = (duration) => {
if (duration.includes(':')) {
// If it's in the format "HH:mm:ss"
const [hours, minutes, seconds] = duration.split(':').map(Number)
return (hours * 3600 + minutes * 60 + seconds) * 1000
} else {
// If it's in the format "nnn ms"
return parseInt(duration)
}
}
const sorted = list.sort((a, b) => parseDuration(a['duration']) - parseDuration(b['duration']))
if (ascending) {
sorted.reverse()
}
return sorted
}
const doInitSort = () => {
const type = storageModule.getSort(manager.initialSort)
const ascending = storageModule.getSortDirection()
const list = manager.testSubset
const initialOrder = ['Error', 'Failed', 'Rerun', 'XFailed', 'XPassed', 'Skipped', 'Passed']
storageModule.setSort(type)
storageModule.setSortDirection(ascending)
if (type?.toLowerCase() === 'original') {
manager.setRender(list)
} else {
let sortedList
switch (type) {
case 'duration':
sortedList = durationSort(list, ascending)
break
case 'result':
sortedList = genericSort(list, type, ascending, initialOrder)
break
default:
sortedList = genericSort(list, type, ascending)
break
}
manager.setRender(sortedList)
}
}
const doSort = (type, skipDirection) => {
const newSortType = storageModule.getSort(manager.initialSort) !== type
const currentAsc = storageModule.getSortDirection()
let ascending
if (skipDirection) {
ascending = currentAsc
} else {
ascending = newSortType ? false : !currentAsc
}
storageModule.setSort(type)
storageModule.setSortDirection(ascending)
const list = manager.testSubset
const sortedList = type === 'duration' ? durationSort(list, ascending) : genericSort(list, type, ascending)
manager.setRender(sortedList)
}
module.exports = {
doInitSort,
doSort,
}
},{"./datamanager.js":1,"./storage.js":8}],8:[function(require,module,exports){
const possibleFilters = [
'passed',
'skipped',
'failed',
'error',
'xfailed',
'xpassed',
'rerun',
]
const getVisible = () => {
const url = new URL(window.location.href)
const settings = new URLSearchParams(url.search).get('visible')
const lower = (item) => {
const lowerItem = item.toLowerCase()
if (possibleFilters.includes(lowerItem)) {
return lowerItem
}
return null
}
return settings === null ?
possibleFilters :
[...new Set(settings?.split(',').map(lower).filter((item) => item))]
}
const hideCategory = (categoryToHide) => {
const url = new URL(window.location.href)
const visibleParams = new URLSearchParams(url.search).get('visible')
const currentVisible = visibleParams ? visibleParams.split(',') : [...possibleFilters]
const settings = [...new Set(currentVisible)].filter((f) => f !== categoryToHide).join(',')
url.searchParams.set('visible', settings)
window.history.pushState({}, null, unescape(url.href))
}
const showCategory = (categoryToShow) => {
if (typeof window === 'undefined') {
return
}
const url = new URL(window.location.href)
const currentVisible = new URLSearchParams(url.search).get('visible')?.split(',').filter(Boolean) ||
[...possibleFilters]
const settings = [...new Set([categoryToShow, ...currentVisible])]
const noFilter = possibleFilters.length === settings.length || !settings.length
noFilter ? url.searchParams.delete('visible') : url.searchParams.set('visible', settings.join(','))
window.history.pushState({}, null, unescape(url.href))
}
const getSort = (initialSort) => {
const url = new URL(window.location.href)
let sort = new URLSearchParams(url.search).get('sort')
if (!sort) {
sort = initialSort || 'result'
}
return sort
}
const setSort = (type) => {
const url = new URL(window.location.href)
url.searchParams.set('sort', type)
window.history.pushState({}, null, unescape(url.href))
}
const getCollapsedCategory = (renderCollapsed) => {
let categories
if (typeof window !== 'undefined') {
const url = new URL(window.location.href)
const collapsedItems = new URLSearchParams(url.search).get('collapsed')
switch (true) {
case !renderCollapsed && collapsedItems === null:
categories = ['passed']
break
case collapsedItems?.length === 0 || /^["']{2}$/.test(collapsedItems):
categories = []
break
case /^all$/.test(collapsedItems) || collapsedItems === null && /^all$/.test(renderCollapsed):
categories = [...possibleFilters]
break
default:
categories = collapsedItems?.split(',').map((item) => item.toLowerCase()) || renderCollapsed
break
}
} else {
categories = []
}
return categories
}
const getSortDirection = () => JSON.parse(sessionStorage.getItem('sortAsc')) || false
const setSortDirection = (ascending) => sessionStorage.setItem('sortAsc', ascending)
const getCollapsedIds = () => JSON.parse(sessionStorage.getItem('collapsedIds')) || []
const setCollapsedIds = (list) => sessionStorage.setItem('collapsedIds', JSON.stringify(list))
module.exports = {
getVisible,
hideCategory,
showCategory,
getCollapsedIds,
setCollapsedIds,
getSort,
setSort,
getSortDirection,
setSortDirection,
getCollapsedCategory,
possibleFilters,
}
},{}]},{},[4]);
</script>
</footer>
</html>
+3
View File
@@ -0,0 +1,3 @@
loguru~=0.7.2
PyYAML~=6.0.1
pytest~=8.2.0
+21
View File
@@ -0,0 +1,21 @@
import pytest
from selenium import webdriver
from pages.interface_0_page_objects import Interface_0
from utils.reader import read_yaml
@pytest.fixture
def driver():
driver = webdriver.Chrome()
# return driver
yield driver
if driver is not None:
driver.quit()
@pytest.fixture
def config():
return read_yaml("C:\\Ankit\\Code\\doczy.ai\\Doczy.AI_Automation\\config\\env.yaml")["environment"]
@@ -0,0 +1,319 @@
body {
font-family: Helvetica, Arial, sans-serif;
font-size: 12px;
/* do not increase min-width as some may use split screens */
min-width: 800px;
color: #999;
}
h1 {
font-size: 24px;
color: black;
}
h2 {
font-size: 16px;
color: black;
}
p {
color: black;
}
a {
color: #999;
}
table {
border-collapse: collapse;
}
/******************************
* SUMMARY INFORMATION
******************************/
#environment td {
padding: 5px;
border: 1px solid #e6e6e6;
vertical-align: top;
}
#environment tr:nth-child(odd) {
background-color: #f6f6f6;
}
#environment ul {
margin: 0;
padding: 0 20px;
}
/******************************
* TEST RESULT COLORS
******************************/
span.passed,
.passed .col-result {
color: green;
}
span.skipped,
span.xfailed,
span.rerun,
.skipped .col-result,
.xfailed .col-result,
.rerun .col-result {
color: orange;
}
span.error,
span.failed,
span.xpassed,
.error .col-result,
.failed .col-result,
.xpassed .col-result {
color: red;
}
.col-links__extra {
margin-right: 3px;
}
/******************************
* RESULTS TABLE
*
* 1. Table Layout
* 2. Extra
* 3. Sorting items
*
******************************/
/*------------------
* 1. Table Layout
*------------------*/
#results-table {
border: 1px solid #e6e6e6;
color: #999;
font-size: 12px;
width: 100%;
}
#results-table th,
#results-table td {
padding: 5px;
border: 1px solid #e6e6e6;
text-align: left;
}
#results-table th {
font-weight: bold;
}
/*------------------
* 2. Extra
*------------------*/
.logwrapper {
max-height: 230px;
overflow-y: scroll;
background-color: #e6e6e6;
}
.logwrapper.expanded {
max-height: none;
}
.logwrapper.expanded .logexpander:after {
content: "collapse [-]";
}
.logwrapper .logexpander {
z-index: 1;
position: sticky;
top: 10px;
width: max-content;
border: 1px solid;
border-radius: 3px;
padding: 5px 7px;
margin: 10px 0 10px calc(100% - 80px);
cursor: pointer;
background-color: #e6e6e6;
}
.logwrapper .logexpander:after {
content: "expand [+]";
}
.logwrapper .logexpander:hover {
color: #000;
border-color: #000;
}
.logwrapper .log {
min-height: 40px;
position: relative;
top: -50px;
height: calc(100% + 50px);
border: 1px solid #e6e6e6;
color: black;
display: block;
font-family: "Courier New", Courier, monospace;
padding: 5px;
padding-right: 80px;
white-space: pre-wrap;
}
div.media {
border: 1px solid #e6e6e6;
float: right;
height: 240px;
margin: 0 5px;
overflow: hidden;
width: 320px;
}
.media-container {
display: grid;
grid-template-columns: 25px auto 25px;
align-items: center;
flex: 1 1;
overflow: hidden;
height: 200px;
}
.media-container--fullscreen {
grid-template-columns: 0px auto 0px;
}
.media-container__nav--right,
.media-container__nav--left {
text-align: center;
cursor: pointer;
}
.media-container__viewport {
cursor: pointer;
text-align: center;
height: inherit;
}
.media-container__viewport img,
.media-container__viewport video {
object-fit: cover;
width: 100%;
max-height: 100%;
}
.media__name,
.media__counter {
display: flex;
flex-direction: row;
justify-content: space-around;
flex: 0 0 25px;
align-items: center;
}
.collapsible td:not(.col-links) {
cursor: pointer;
}
.collapsible td:not(.col-links):hover::after {
color: #bbb;
font-style: italic;
cursor: pointer;
}
.col-result {
width: 130px;
}
.col-result:hover::after {
content: " (hide details)";
}
.col-result.collapsed:hover::after {
content: " (show details)";
}
#environment-header h2:hover::after {
content: " (hide details)";
color: #bbb;
font-style: italic;
cursor: pointer;
font-size: 12px;
}
#environment-header.collapsed h2:hover::after {
content: " (show details)";
color: #bbb;
font-style: italic;
cursor: pointer;
font-size: 12px;
}
/*------------------
* 3. Sorting items
*------------------*/
.sortable {
cursor: pointer;
}
.sortable.desc:after {
content: " ";
position: relative;
left: 5px;
bottom: -12.5px;
border: 10px solid #4caf50;
border-bottom: 0;
border-left-color: transparent;
border-right-color: transparent;
}
.sortable.asc:after {
content: " ";
position: relative;
left: 5px;
bottom: 12.5px;
border: 10px solid #4caf50;
border-top: 0;
border-left-color: transparent;
border-right-color: transparent;
}
.hidden, .summary__reload__button.hidden {
display: none;
}
.summary__data {
flex: 0 0 550px;
}
.summary__reload {
flex: 1 1;
display: flex;
justify-content: center;
}
.summary__reload__button {
flex: 0 0 300px;
display: flex;
color: white;
font-weight: bold;
background-color: #4caf50;
text-align: center;
justify-content: center;
align-items: center;
border-radius: 3px;
cursor: pointer;
}
.summary__reload__button:hover {
background-color: #46a049;
}
.summary__spacer {
flex: 0 0 550px;
}
.controls {
display: flex;
justify-content: space-between;
}
.filters,
.collapse {
display: flex;
align-items: center;
}
.filters button,
.collapse button {
color: #999;
border: none;
background: none;
cursor: pointer;
text-decoration: underline;
}
.filters button:hover,
.collapse button:hover {
color: #ccc;
}
.filter__label {
margin-right: 10px;
}
@@ -0,0 +1,770 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title id="head-title">test_report.html</title>
<link href="assets\style.css" rel="stylesheet" type="text/css"/>
</head>
<body>
<h1 id="title">test_report.html</h1>
<p>Report generated on 07-May-2024 at 17:55:59 by <a href="https://pypi.python.org/pypi/pytest-html">pytest-html</a>
v4.1.1</p>
<div id="environment-header">
<h2>Environment</h2>
</div>
<table id="environment"></table>
<!-- TEMPLATES -->
<template id="template_environment_row">
<tr>
<td></td>
<td></td>
</tr>
</template>
<template id="template_results-table__body--empty">
<tbody class="results-table-row">
<tr id="not-found-message">
<td colspan="4">No results found. Check the filters.</th>
</tr>
</template>
<template id="template_results-table__tbody">
<tbody class="results-table-row">
<tr class="collapsible">
</tr>
<tr class="extras-row">
<td class="extra" colspan="4">
<div class="extraHTML"></div>
<div class="media">
<div class="media-container">
<div class="media-container__nav--left"><</div>
<div class="media-container__viewport">
<img src="" />
<video controls>
<source src="" type="video/mp4">
</video>
</div>
<div class="media-container__nav--right">></div>
</div>
<div class="media__name"></div>
<div class="media__counter"></div>
</div>
<div class="logwrapper">
<div class="logexpander"></div>
<div class="log"></div>
</div>
</td>
</tr>
</tbody>
</template>
<!-- END TEMPLATES -->
<div class="summary">
<div class="summary__data">
<h2>Summary</h2>
<div class="additional-summary prefix">
</div>
<p class="run-count">1 test took 00:00:09.</p>
<p class="filter">(Un)check the boxes to filter the results.</p>
<div class="summary__reload">
<div class="summary__reload__button hidden" onclick="location.reload()">
<div>There are still tests running. <br />Reload this page to get the latest results!</div>
</div>
</div>
<div class="summary__spacer"></div>
<div class="controls">
<div class="filters">
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="failed" disabled/>
<span class="failed">0 Failed,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="passed" />
<span class="passed">1 Passed,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="skipped" disabled/>
<span class="skipped">0 Skipped,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xfailed" disabled/>
<span class="xfailed">0 Expected failures,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="xpassed" disabled/>
<span class="xpassed">0 Unexpected passes,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="error" disabled/>
<span class="error">0 Errors,</span>
<input checked="true" class="filter" name="filter_checkbox" type="checkbox" data-test-result="rerun" disabled/>
<span class="rerun">0 Reruns</span>
</div>
<div class="collapse">
<button id="show_all_details">Show all details</button>&nbsp;/&nbsp;<button id="hide_all_details">Hide all details</button>
</div>
</div>
</div>
<div class="additional-summary summary">
</div>
<div class="additional-summary postfix">
</div>
</div>
<table id="results-table">
<thead id="results-table-head">
<tr>
<th class="sortable" data-column-type="result">Result</th>
<th class="sortable" data-column-type="testId">Test</th>
<th class="sortable" data-column-type="duration">Duration</th>
<th>Links</th>
</tr>
</thead>
</table>
</body>
<footer>
<div id="data-container" data-jsonblob="{&#34;environment&#34;: {&#34;Python&#34;: &#34;3.12.3&#34;, &#34;Platform&#34;: &#34;Windows-10-10.0.19045-SP0&#34;, &#34;Packages&#34;: {&#34;pytest&#34;: &#34;8.2.0&#34;, &#34;pluggy&#34;: &#34;1.5.0&#34;}, &#34;Plugins&#34;: {&#34;html&#34;: &#34;4.1.1&#34;, &#34;metadata&#34;: &#34;3.1.1&#34;}}, &#34;tests&#34;: {&#34;tests/test_interface_0.py::Test_interface_0::test_validate_navigation&#34;: [{&#34;extras&#34;: [], &#34;result&#34;: &#34;Passed&#34;, &#34;testId&#34;: &#34;tests/test_interface_0.py::Test_interface_0::test_validate_navigation&#34;, &#34;duration&#34;: &#34;00:00:09&#34;, &#34;resultsTableRow&#34;: [&#34;&lt;td class=\&#34;col-result\&#34;&gt;Passed&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-testId\&#34;&gt;tests/test_interface_0.py::Test_interface_0::test_validate_navigation&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-duration\&#34;&gt;00:00:09&lt;/td&gt;&#34;, &#34;&lt;td class=\&#34;col-links\&#34;&gt;&lt;/td&gt;&#34;], &#34;log&#34;: &#34;----------------------------- Captured stderr call -----------------------------\n2024-05-07 17:55:47.858 | INFO | tests.test_interface_0:test_validate_navigation:11 - Opening URL https://doczy.aarete.com:8500/\n2024-05-07 17:55:51.520 | INFO | tests.test_interface_0:test_validate_navigation:13 - URL https://doczy.aarete.com:8500/ opened\n&#34;}]}, &#34;renderCollapsed&#34;: [&#34;passed&#34;], &#34;initialSort&#34;: &#34;result&#34;, &#34;title&#34;: &#34;test_report.html&#34;}"></div>
<script>
(function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
const { getCollapsedCategory, setCollapsedIds } = require('./storage.js')
class DataManager {
setManager(data) {
const collapsedCategories = [...getCollapsedCategory(data.renderCollapsed)]
const collapsedIds = []
const tests = Object.values(data.tests).flat().map((test, index) => {
const collapsed = collapsedCategories.includes(test.result.toLowerCase())
const id = `test_${index}`
if (collapsed) {
collapsedIds.push(id)
}
return {
...test,
id,
collapsed,
}
})
const dataBlob = { ...data, tests }
this.data = { ...dataBlob }
this.renderData = { ...dataBlob }
setCollapsedIds(collapsedIds)
}
get allData() {
return { ...this.data }
}
resetRender() {
this.renderData = { ...this.data }
}
setRender(data) {
this.renderData.tests = [...data]
}
toggleCollapsedItem(id) {
this.renderData.tests = this.renderData.tests.map((test) =>
test.id === id ? { ...test, collapsed: !test.collapsed } : test,
)
}
set allCollapsed(collapsed) {
this.renderData = { ...this.renderData, tests: [...this.renderData.tests.map((test) => (
{ ...test, collapsed }
))] }
}
get testSubset() {
return [...this.renderData.tests]
}
get environment() {
return this.renderData.environment
}
get initialSort() {
return this.data.initialSort
}
}
module.exports = {
manager: new DataManager(),
}
},{"./storage.js":8}],2:[function(require,module,exports){
const mediaViewer = require('./mediaviewer.js')
const templateEnvRow = document.getElementById('template_environment_row')
const templateResult = document.getElementById('template_results-table__tbody')
function htmlToElements(html) {
const temp = document.createElement('template')
temp.innerHTML = html
return temp.content.childNodes
}
const find = (selector, elem) => {
if (!elem) {
elem = document
}
return elem.querySelector(selector)
}
const findAll = (selector, elem) => {
if (!elem) {
elem = document
}
return [...elem.querySelectorAll(selector)]
}
const dom = {
getStaticRow: (key, value) => {
const envRow = templateEnvRow.content.cloneNode(true)
const isObj = typeof value === 'object' && value !== null
const values = isObj ? Object.keys(value).map((k) => `${k}: ${value[k]}`) : null
const valuesElement = htmlToElements(
values ? `<ul>${values.map((val) => `<li>${val}</li>`).join('')}<ul>` : `<div>${value}</div>`)[0]
const td = findAll('td', envRow)
td[0].textContent = key
td[1].appendChild(valuesElement)
return envRow
},
getResultTBody: ({ testId, id, log, extras, resultsTableRow, tableHtml, result, collapsed }) => {
const resultBody = templateResult.content.cloneNode(true)
resultBody.querySelector('tbody').classList.add(result.toLowerCase())
resultBody.querySelector('tbody').id = testId
resultBody.querySelector('.collapsible').dataset.id = id
resultsTableRow.forEach((html) => {
const t = document.createElement('template')
t.innerHTML = html
resultBody.querySelector('.collapsible').appendChild(t.content)
})
if (log) {
// Wrap lines starting with "E" with span.error to color those lines red
const wrappedLog = log.replace(/^E.*$/gm, (match) => `<span class="error">${match}</span>`)
resultBody.querySelector('.log').innerHTML = wrappedLog
} else {
resultBody.querySelector('.log').remove()
}
if (collapsed) {
resultBody.querySelector('.collapsible > td')?.classList.add('collapsed')
resultBody.querySelector('.extras-row').classList.add('hidden')
} else {
resultBody.querySelector('.collapsible > td')?.classList.remove('collapsed')
}
const media = []
extras?.forEach(({ name, format_type, content }) => {
if (['image', 'video'].includes(format_type)) {
media.push({ path: content, name, format_type })
}
if (format_type === 'html') {
resultBody.querySelector('.extraHTML').insertAdjacentHTML('beforeend', `<div>${content}</div>`)
}
})
mediaViewer.setup(resultBody, media)
// Add custom html from the pytest_html_results_table_html hook
tableHtml?.forEach((item) => {
resultBody.querySelector('td[class="extra"]').insertAdjacentHTML('beforeend', item)
})
return resultBody
},
}
module.exports = {
dom,
htmlToElements,
find,
findAll,
}
},{"./mediaviewer.js":6}],3:[function(require,module,exports){
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const storageModule = require('./storage.js')
const getFilteredSubSet = (filter) =>
manager.allData.tests.filter(({ result }) => filter.includes(result.toLowerCase()))
const doInitFilter = () => {
const currentFilter = storageModule.getVisible()
const filteredSubset = getFilteredSubSet(currentFilter)
manager.setRender(filteredSubset)
}
const doFilter = (type, show) => {
if (show) {
storageModule.showCategory(type)
} else {
storageModule.hideCategory(type)
}
const currentFilter = storageModule.getVisible()
const filteredSubset = getFilteredSubSet(currentFilter)
manager.setRender(filteredSubset)
const sortColumn = storageModule.getSort()
doSort(sortColumn, true)
}
module.exports = {
doFilter,
doInitFilter,
}
},{"./datamanager.js":1,"./sort.js":7,"./storage.js":8}],4:[function(require,module,exports){
const { redraw, bindEvents, renderStatic } = require('./main.js')
const { doInitFilter } = require('./filter.js')
const { doInitSort } = require('./sort.js')
const { manager } = require('./datamanager.js')
const data = JSON.parse(document.getElementById('data-container').dataset.jsonblob)
function init() {
manager.setManager(data)
doInitFilter()
doInitSort()
renderStatic()
redraw()
bindEvents()
}
init()
},{"./datamanager.js":1,"./filter.js":3,"./main.js":5,"./sort.js":7}],5:[function(require,module,exports){
const { dom, find, findAll } = require('./dom.js')
const { manager } = require('./datamanager.js')
const { doSort } = require('./sort.js')
const { doFilter } = require('./filter.js')
const {
getVisible,
getCollapsedIds,
setCollapsedIds,
getSort,
getSortDirection,
possibleFilters,
} = require('./storage.js')
const removeChildren = (node) => {
while (node.firstChild) {
node.removeChild(node.firstChild)
}
}
const renderStatic = () => {
const renderEnvironmentTable = () => {
const environment = manager.environment
const rows = Object.keys(environment).map((key) => dom.getStaticRow(key, environment[key]))
const table = document.getElementById('environment')
removeChildren(table)
rows.forEach((row) => table.appendChild(row))
}
renderEnvironmentTable()
}
const addItemToggleListener = (elem) => {
elem.addEventListener('click', ({ target }) => {
const id = target.parentElement.dataset.id
manager.toggleCollapsedItem(id)
const collapsedIds = getCollapsedIds()
if (collapsedIds.includes(id)) {
const updated = collapsedIds.filter((item) => item !== id)
setCollapsedIds(updated)
} else {
collapsedIds.push(id)
setCollapsedIds(collapsedIds)
}
redraw()
})
}
const renderContent = (tests) => {
const sortAttr = getSort(manager.initialSort)
const sortAsc = JSON.parse(getSortDirection())
const rows = tests.map(dom.getResultTBody)
const table = document.getElementById('results-table')
const tableHeader = document.getElementById('results-table-head')
const newTable = document.createElement('table')
newTable.id = 'results-table'
// remove all sorting classes and set the relevant
findAll('.sortable', tableHeader).forEach((elem) => elem.classList.remove('asc', 'desc'))
tableHeader.querySelector(`.sortable[data-column-type="${sortAttr}"]`)?.classList.add(sortAsc ? 'desc' : 'asc')
newTable.appendChild(tableHeader)
if (!rows.length) {
const emptyTable = document.getElementById('template_results-table__body--empty').content.cloneNode(true)
newTable.appendChild(emptyTable)
} else {
rows.forEach((row) => {
if (!!row) {
findAll('.collapsible td:not(.col-links', row).forEach(addItemToggleListener)
find('.logexpander', row).addEventListener('click',
(evt) => evt.target.parentNode.classList.toggle('expanded'),
)
newTable.appendChild(row)
}
})
}
table.replaceWith(newTable)
}
const renderDerived = () => {
const currentFilter = getVisible()
possibleFilters.forEach((result) => {
const input = document.querySelector(`input[data-test-result="${result}"]`)
input.checked = currentFilter.includes(result)
})
}
const bindEvents = () => {
const filterColumn = (evt) => {
const { target: element } = evt
const { testResult } = element.dataset
doFilter(testResult, element.checked)
const collapsedIds = getCollapsedIds()
const updated = manager.renderData.tests.map((test) => {
return {
...test,
collapsed: collapsedIds.includes(test.id),
}
})
manager.setRender(updated)
redraw()
}
const header = document.getElementById('environment-header')
header.addEventListener('click', () => {
const table = document.getElementById('environment')
table.classList.toggle('hidden')
header.classList.toggle('collapsed')
})
findAll('input[name="filter_checkbox"]').forEach((elem) => {
elem.addEventListener('click', filterColumn)
})
findAll('.sortable').forEach((elem) => {
elem.addEventListener('click', (evt) => {
const { target: element } = evt
const { columnType } = element.dataset
doSort(columnType)
redraw()
})
})
document.getElementById('show_all_details').addEventListener('click', () => {
manager.allCollapsed = false
setCollapsedIds([])
redraw()
})
document.getElementById('hide_all_details').addEventListener('click', () => {
manager.allCollapsed = true
const allIds = manager.renderData.tests.map((test) => test.id)
setCollapsedIds(allIds)
redraw()
})
}
const redraw = () => {
const { testSubset } = manager
renderContent(testSubset)
renderDerived()
}
module.exports = {
redraw,
bindEvents,
renderStatic,
}
},{"./datamanager.js":1,"./dom.js":2,"./filter.js":3,"./sort.js":7,"./storage.js":8}],6:[function(require,module,exports){
class MediaViewer {
constructor(assets) {
this.assets = assets
this.index = 0
}
nextActive() {
this.index = this.index === this.assets.length - 1 ? 0 : this.index + 1
return [this.activeFile, this.index]
}
prevActive() {
this.index = this.index === 0 ? this.assets.length - 1 : this.index -1
return [this.activeFile, this.index]
}
get currentIndex() {
return this.index
}
get activeFile() {
return this.assets[this.index]
}
}
const setup = (resultBody, assets) => {
if (!assets.length) {
resultBody.querySelector('.media').classList.add('hidden')
return
}
const mediaViewer = new MediaViewer(assets)
const container = resultBody.querySelector('.media-container')
const leftArrow = resultBody.querySelector('.media-container__nav--left')
const rightArrow = resultBody.querySelector('.media-container__nav--right')
const mediaName = resultBody.querySelector('.media__name')
const counter = resultBody.querySelector('.media__counter')
const imageEl = resultBody.querySelector('img')
const sourceEl = resultBody.querySelector('source')
const videoEl = resultBody.querySelector('video')
const setImg = (media, index) => {
if (media?.format_type === 'image') {
imageEl.src = media.path
imageEl.classList.remove('hidden')
videoEl.classList.add('hidden')
} else if (media?.format_type === 'video') {
sourceEl.src = media.path
videoEl.classList.remove('hidden')
imageEl.classList.add('hidden')
}
mediaName.innerText = media?.name
counter.innerText = `${index + 1} / ${assets.length}`
}
setImg(mediaViewer.activeFile, mediaViewer.currentIndex)
const moveLeft = () => {
const [media, index] = mediaViewer.prevActive()
setImg(media, index)
}
const doRight = () => {
const [media, index] = mediaViewer.nextActive()
setImg(media, index)
}
const openImg = () => {
window.open(mediaViewer.activeFile.path, '_blank')
}
if (assets.length === 1) {
container.classList.add('media-container--fullscreen')
} else {
leftArrow.addEventListener('click', moveLeft)
rightArrow.addEventListener('click', doRight)
}
imageEl.addEventListener('click', openImg)
}
module.exports = {
setup,
}
},{}],7:[function(require,module,exports){
const { manager } = require('./datamanager.js')
const storageModule = require('./storage.js')
const genericSort = (list, key, ascending, customOrder) => {
let sorted
if (customOrder) {
sorted = list.sort((a, b) => {
const aValue = a.result.toLowerCase()
const bValue = b.result.toLowerCase()
const aIndex = customOrder.findIndex((item) => item.toLowerCase() === aValue)
const bIndex = customOrder.findIndex((item) => item.toLowerCase() === bValue)
// Compare the indices to determine the sort order
return aIndex - bIndex
})
} else {
sorted = list.sort((a, b) => a[key] === b[key] ? 0 : a[key] > b[key] ? 1 : -1)
}
if (ascending) {
sorted.reverse()
}
return sorted
}
const durationSort = (list, ascending) => {
const parseDuration = (duration) => {
if (duration.includes(':')) {
// If it's in the format "HH:mm:ss"
const [hours, minutes, seconds] = duration.split(':').map(Number)
return (hours * 3600 + minutes * 60 + seconds) * 1000
} else {
// If it's in the format "nnn ms"
return parseInt(duration)
}
}
const sorted = list.sort((a, b) => parseDuration(a['duration']) - parseDuration(b['duration']))
if (ascending) {
sorted.reverse()
}
return sorted
}
const doInitSort = () => {
const type = storageModule.getSort(manager.initialSort)
const ascending = storageModule.getSortDirection()
const list = manager.testSubset
const initialOrder = ['Error', 'Failed', 'Rerun', 'XFailed', 'XPassed', 'Skipped', 'Passed']
storageModule.setSort(type)
storageModule.setSortDirection(ascending)
if (type?.toLowerCase() === 'original') {
manager.setRender(list)
} else {
let sortedList
switch (type) {
case 'duration':
sortedList = durationSort(list, ascending)
break
case 'result':
sortedList = genericSort(list, type, ascending, initialOrder)
break
default:
sortedList = genericSort(list, type, ascending)
break
}
manager.setRender(sortedList)
}
}
const doSort = (type, skipDirection) => {
const newSortType = storageModule.getSort(manager.initialSort) !== type
const currentAsc = storageModule.getSortDirection()
let ascending
if (skipDirection) {
ascending = currentAsc
} else {
ascending = newSortType ? false : !currentAsc
}
storageModule.setSort(type)
storageModule.setSortDirection(ascending)
const list = manager.testSubset
const sortedList = type === 'duration' ? durationSort(list, ascending) : genericSort(list, type, ascending)
manager.setRender(sortedList)
}
module.exports = {
doInitSort,
doSort,
}
},{"./datamanager.js":1,"./storage.js":8}],8:[function(require,module,exports){
const possibleFilters = [
'passed',
'skipped',
'failed',
'error',
'xfailed',
'xpassed',
'rerun',
]
const getVisible = () => {
const url = new URL(window.location.href)
const settings = new URLSearchParams(url.search).get('visible')
const lower = (item) => {
const lowerItem = item.toLowerCase()
if (possibleFilters.includes(lowerItem)) {
return lowerItem
}
return null
}
return settings === null ?
possibleFilters :
[...new Set(settings?.split(',').map(lower).filter((item) => item))]
}
const hideCategory = (categoryToHide) => {
const url = new URL(window.location.href)
const visibleParams = new URLSearchParams(url.search).get('visible')
const currentVisible = visibleParams ? visibleParams.split(',') : [...possibleFilters]
const settings = [...new Set(currentVisible)].filter((f) => f !== categoryToHide).join(',')
url.searchParams.set('visible', settings)
window.history.pushState({}, null, unescape(url.href))
}
const showCategory = (categoryToShow) => {
if (typeof window === 'undefined') {
return
}
const url = new URL(window.location.href)
const currentVisible = new URLSearchParams(url.search).get('visible')?.split(',').filter(Boolean) ||
[...possibleFilters]
const settings = [...new Set([categoryToShow, ...currentVisible])]
const noFilter = possibleFilters.length === settings.length || !settings.length
noFilter ? url.searchParams.delete('visible') : url.searchParams.set('visible', settings.join(','))
window.history.pushState({}, null, unescape(url.href))
}
const getSort = (initialSort) => {
const url = new URL(window.location.href)
let sort = new URLSearchParams(url.search).get('sort')
if (!sort) {
sort = initialSort || 'result'
}
return sort
}
const setSort = (type) => {
const url = new URL(window.location.href)
url.searchParams.set('sort', type)
window.history.pushState({}, null, unescape(url.href))
}
const getCollapsedCategory = (renderCollapsed) => {
let categories
if (typeof window !== 'undefined') {
const url = new URL(window.location.href)
const collapsedItems = new URLSearchParams(url.search).get('collapsed')
switch (true) {
case !renderCollapsed && collapsedItems === null:
categories = ['passed']
break
case collapsedItems?.length === 0 || /^["']{2}$/.test(collapsedItems):
categories = []
break
case /^all$/.test(collapsedItems) || collapsedItems === null && /^all$/.test(renderCollapsed):
categories = [...possibleFilters]
break
default:
categories = collapsedItems?.split(',').map((item) => item.toLowerCase()) || renderCollapsed
break
}
} else {
categories = []
}
return categories
}
const getSortDirection = () => JSON.parse(sessionStorage.getItem('sortAsc')) || false
const setSortDirection = (ascending) => sessionStorage.setItem('sortAsc', ascending)
const getCollapsedIds = () => JSON.parse(sessionStorage.getItem('collapsedIds')) || []
const setCollapsedIds = (list) => sessionStorage.setItem('collapsedIds', JSON.stringify(list))
module.exports = {
getVisible,
hideCategory,
showCategory,
getCollapsedIds,
setCollapsedIds,
getSort,
setSort,
getSortDirection,
setSortDirection,
getCollapsedCategory,
possibleFilters,
}
},{}]},{},[4]);
</script>
</footer>
</html>
@@ -0,0 +1,29 @@
from utils.common_methods import get_title
from utils.common_methods2 import sign_in
from utils.logger import get_logger
class Test_interface_0:
logger = get_logger()
def test_validate_navigation(self, driver, config):
self.logger.info(f"Opening URL {config['url']}")
driver.get(config['url'])
self.logger.info(f"URL {config['url']} opened")
get_title(driver, "interface_0 · Streamlit")
if driver.title == 'interface_0 · Streamlit':
assert True
else:
assert False
def test_interface_0(self, driver, config):
self.logger.info(f"Opening URL {config['url']}")
driver.get(config['url'])
self.logger.info(f"URL {config['url']} opened")
sign_in(driver, config)
get_title(driver, "interface_0 · Streamlit")
if driver.title == 'interface_0 · Streamlit':
assert True
else:
assert False
@@ -0,0 +1,23 @@
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
def get_clickable_element(driver, By, element_id):
return WebDriverWait(driver, timeout=50).until(
ec.element_to_be_clickable((By, element_id))
)
def get_element(driver, By, element_id):
return WebDriverWait(driver, timeout=50).until(
ec.visibility_of_element_located((By, element_id))
)
def get_title(driver, title):
return WebDriverWait(driver, timeout=50).until(
ec.title_contains(title)
)
@@ -0,0 +1,20 @@
from pages.Email_sign_in_page import Email_sign_in_page
from pages.Password_sign_in_page import Password_sign_in_page
from pages.Pre_sign_in_page import Pre_sign_in_page
from pages.Remember_sign_in_page import Remember_sign_in_page
from utils.logger import get_logger
logger = get_logger()
def sign_in(driver, config):
pre_sign_in_page = Pre_sign_in_page(driver)
pre_sign_in_page.click_sign_in_link()
logger.info(f"Adding email")
email_sign_in_page = Email_sign_in_page(driver)
email_sign_in_page.sign_in(config)
logger.info(f"Email added")
password_sign_in_page = Password_sign_in_page(driver)
password_sign_in_page.sign_in(config)
remember_sign_in_page = Remember_sign_in_page(driver)
remember_sign_in_page.click_no_btn()
+8
View File
@@ -0,0 +1,8 @@
from loguru import logger
def setup_logger(logfile):
logger.add(logfile)
def get_logger():
return logger
+6
View File
@@ -0,0 +1,6 @@
import yaml
def read_yaml(file_path):
with open (file_path,'r') as file:
return yaml.safe_load(file)
+10
View File
@@ -0,0 +1,10 @@
import pytest
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
outcome = yield
rep = outcome.get_result()
# if rep.when == "call":