From 309f6d93c8fb4d40c95dcd6afcaf9d659ae5a345 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 13:14:00 +0300 Subject: [PATCH 01/13] fixed archive links error if set default permalinks --- classes/class-archive-mapping.php | 41 ++++++++++++++++++------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/classes/class-archive-mapping.php b/classes/class-archive-mapping.php index 934cd52a..999f1b9a 100644 --- a/classes/class-archive-mapping.php +++ b/classes/class-archive-mapping.php @@ -238,11 +238,13 @@ public function converting_load_more_and_infinite_paginate_next_page_to_friendly * @return array */ public function converting_paginate_links_to_friendly_url( $arr, $args, $vp_options ) { + $permalink_structure = get_option( 'permalink_structure' ); // Determine if a page is an archive. if ( self::is_archive( $vp_options ) && isset( $arr ) && - ! empty( $arr ) + ! empty( $arr ) && + ! empty( $permalink_structure ) ) { if ( $arr['url'] ) { // Parsing the content of links. @@ -1264,24 +1266,28 @@ private function get_relative_archive_link() { * @return string */ private function converting_paginate_link_to_friendly_url( $link, $num_page = null ) { - // Parsing the content of links. - preg_match( '/vp_page=(\d+)/', $link, $match_vp_page ); - preg_match( '/page\/(\d+)/', $link, $match_page ); + $permalink_structure = get_option( 'permalink_structure' ); - if ( empty( $num_page ) && is_array( $match_vp_page ) && ! empty( $match_vp_page ) ) { - $num_page = $match_vp_page[1]; - } + if ( ! empty( $permalink_structure ) ) { + // Parsing the content of links. + preg_match( '/vp_page=(\d+)/', $link, $match_vp_page ); + preg_match( '/page\/(\d+)/', $link, $match_page ); - if ( ! empty( $num_page ) && is_array( $match_page ) && ! empty( $match_page ) ) { - $link = str_replace( $match_page[0], 'page/' . $num_page, $link ); - } + if ( empty( $num_page ) && is_array( $match_vp_page ) && ! empty( $match_vp_page ) ) { + $num_page = $match_vp_page[1]; + } - if ( ! empty( $num_page ) && empty( $match_page ) ) { - $link = str_replace( '/?', '/page/' . $num_page . '/?', $link ); - } + if ( ! empty( $num_page ) && is_array( $match_page ) && ! empty( $match_page ) ) { + $link = str_replace( $match_page[0], 'page/' . $num_page, $link ); + } + + if ( ! empty( $num_page ) && empty( $match_page ) ) { + $link = str_replace( '/?', '/page/' . $num_page . '/?', $link ); + } - if ( strpos( $link, 'vp_page' ) !== false ) { - $link = remove_query_arg( 'vp_page', $link ); + if ( strpos( $link, 'vp_page' ) !== false ) { + $link = remove_query_arg( 'vp_page', $link ); + } } return $link; @@ -1298,9 +1304,10 @@ private function converting_paginate_link_to_friendly_url( $link, $num_page = nu */ private function convert_category_to_friendly_url( $category_url ) { preg_match( '/vp_filter=([^&]*)/', $category_url, $match_filter ); - $base_page = $this->get_relative_archive_link(); + $base_page = $this->get_relative_archive_link(); + $permalink_structure = get_option( 'permalink_structure' ); - if ( is_array( $match_filter ) && ! empty( $match_filter ) ) { + if ( is_array( $match_filter ) && ! empty( $match_filter ) && ! empty( $permalink_structure ) ) { // We extract the contents of the filter and form a new link. $taxonomies = explode( ':', rawurldecode( $match_filter[1] ) ); if ( is_array( $taxonomies ) && 'portfolio_category' === $taxonomies[0] ) { From f5963ef8e73eaa6cbc8932407f3a531b88a26432 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 13:44:27 +0300 Subject: [PATCH 02/13] added a utility to delete the entire portfolio to clean up the CMS container after running a test --- tests/e2e/utils/delete-all-portfolio.js | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tests/e2e/utils/delete-all-portfolio.js diff --git a/tests/e2e/utils/delete-all-portfolio.js b/tests/e2e/utils/delete-all-portfolio.js new file mode 100644 index 00000000..88425b1a --- /dev/null +++ b/tests/e2e/utils/delete-all-portfolio.js @@ -0,0 +1,31 @@ +/** + * Delete all posts using REST API. + * + * @param this + * @param this.requestUtils + */ +export async function deleteAllPortfolio({ requestUtils }) { + // List all portfolio posts. + const posts = await requestUtils.rest({ + path: '/wp/v2/portfolio', + params: { + per_page: 100, + // All possible statuses. + status: 'publish,future,draft,pending,private,trash', + }, + }); + + // Delete all portfolio one by one. + // "/wp/v2/posts" not yet supports batch requests. + await Promise.all( + posts.map((post) => + requestUtils.rest({ + method: 'DELETE', + path: `/wp/v2/portfolio/${post.id}`, + params: { + force: true, + }, + }) + ) + ); +} From 20b31badeee8bcd32a7f40893761b615a111c8aa Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 13:45:17 +0300 Subject: [PATCH 03/13] added forcing install wordpress/prettier-config package --- package-lock.json | 166 ++++++++++++++++++++++------------------------ 1 file changed, 78 insertions(+), 88 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9a2e97b4..e7b1eca5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3269,7 +3269,6 @@ "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" @@ -4210,7 +4209,6 @@ "version": "9.6.0", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.0.tgz", "integrity": "sha512-gi6WQJ7cHRgZxtkQEoyHMppPjq9Kxo5Tjn2prSKDSmZrCz8TZ3jSRCeTJm+WoM+oB0WG37bRqLzaaU3q7JypGg==", - "dev": true, "dependencies": { "@types/estree": "*", "@types/json-schema": "*" @@ -4220,7 +4218,6 @@ "version": "3.7.7", "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, "dependencies": { "@types/eslint": "*", "@types/estree": "*" @@ -4229,8 +4226,7 @@ "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", - "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", - "dev": true + "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==" }, "node_modules/@types/express": { "version": "4.17.21", @@ -4373,7 +4369,6 @@ "version": "20.14.12", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.12.tgz", "integrity": "sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==", - "dev": true, "dependencies": { "undici-types": "~5.26.4" } @@ -4859,7 +4854,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", - "dev": true, "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" @@ -4868,26 +4862,22 @@ "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", - "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", - "dev": true + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", - "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", - "dev": true + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", - "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", - "dev": true + "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", - "dev": true, "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", @@ -4897,14 +4887,12 @@ "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", - "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", - "dev": true + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -4916,7 +4904,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", - "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } @@ -4925,7 +4912,6 @@ "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", - "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } @@ -4933,14 +4919,12 @@ "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", - "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", - "dev": true + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -4956,7 +4940,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", @@ -4969,7 +4952,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", @@ -4981,7 +4963,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", @@ -4995,7 +4976,6 @@ "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", - "dev": true, "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" @@ -5638,14 +5618,12 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" }, "node_modules/abab": { "version": "2.0.6", @@ -5676,7 +5654,6 @@ "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", - "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -5698,7 +5675,6 @@ "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", - "dev": true, "peerDependencies": { "acorn": "^8" } @@ -5762,7 +5738,6 @@ "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5823,7 +5798,6 @@ "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "dev": true, "peerDependencies": { "ajv": "^6.9.1" } @@ -6947,7 +6921,6 @@ "version": "4.23.2", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7020,8 +6993,7 @@ "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, "node_modules/builtin-modules": { "version": "3.3.0", @@ -7176,7 +7148,6 @@ "version": "1.0.30001643", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", - "dev": true, "funding": [ { "type": "opencollective", @@ -7423,7 +7394,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, "engines": { "node": ">=6.0" } @@ -9550,8 +9520,7 @@ "node_modules/electron-to-chromium": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.1.tgz", - "integrity": "sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w==", - "dev": true + "integrity": "sha512-FKbOCOQ5QRB3VlIbl1LZQefWIYwszlBloaXcY2rbfpu9ioJnNh3TK03YtIDKDo3WKBi8u+YV4+Fn2CkEozgf4w==" }, "node_modules/emittery": { "version": "0.13.1", @@ -9623,7 +9592,6 @@ "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" @@ -9815,8 +9783,7 @@ "node_modules/es-module-lexer": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", - "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", - "dev": true + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==" }, "node_modules/es-object-atoms": { "version": "1.0.0", @@ -9874,7 +9841,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", - "dev": true, "engines": { "node": ">=6" } @@ -10512,7 +10478,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" @@ -10525,7 +10490,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, "engines": { "node": ">=4.0" } @@ -10870,7 +10834,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, "dependencies": { "estraverse": "^5.2.0" }, @@ -10882,7 +10845,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, "engines": { "node": ">=4.0" } @@ -10920,7 +10882,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, "engines": { "node": ">=0.8.x" } @@ -11262,8 +11223,7 @@ "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "node_modules/fast-levenshtein": { "version": "2.0.6", @@ -12222,8 +12182,7 @@ "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" }, "node_modules/glob-watcher": { "version": "6.0.0", @@ -12401,8 +12360,7 @@ "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, "node_modules/graphemer": { "version": "1.4.0", @@ -16007,6 +15965,12 @@ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==", "dev": true }, + "node_modules/jquery": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz", + "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==", + "peer": true + }, "node_modules/js-library-detector": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/js-library-detector/-/js-library-detector-6.7.0.tgz", @@ -16131,8 +16095,7 @@ "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", @@ -16959,7 +16922,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", - "dev": true, "engines": { "node": ">=6.11.5" } @@ -17683,8 +17645,7 @@ "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" }, "node_modules/merge2": { "version": "1.4.1", @@ -17737,7 +17698,6 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -17746,7 +17706,6 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, "dependencies": { "mime-db": "1.52.0" }, @@ -17996,8 +17955,7 @@ "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" }, "node_modules/netmask": { "version": "2.0.2", @@ -18084,8 +18042,7 @@ "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==" }, "node_modules/nomnom": { "version": "1.8.1", @@ -20227,6 +20184,22 @@ "node": ">= 0.8.0" } }, + "node_modules/prettier": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", + "dev": true, + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, "node_modules/prettier-linter-helpers": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", @@ -20449,7 +20422,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, "engines": { "node": ">=6" } @@ -20665,7 +20637,6 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dev": true, "dependencies": { "loose-envify": "^1.1.0" }, @@ -20689,6 +20660,19 @@ "react-dom": "^0.13.0 || ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, "node_modules/react-is": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", @@ -21597,6 +21581,15 @@ "node": ">=v12.22.7" } }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/schema-utils": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz", @@ -23140,7 +23133,6 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, "engines": { "node": ">=6" } @@ -23216,7 +23208,6 @@ "version": "5.31.3", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.3.tgz", "integrity": "sha512-pAfYn3NIZLyZpa83ZKigvj6Rn9c/vd5KfYGX7cN1mnzqgDcxWvrU5ZtAfIKhEXz9nRecw4z3LXkjaq96/qZqAA==", - "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", @@ -23234,7 +23225,6 @@ "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", - "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", @@ -23268,7 +23258,6 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, "engines": { "node": ">=8" } @@ -23277,7 +23266,6 @@ "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", @@ -23291,7 +23279,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", @@ -23309,7 +23296,6 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -23323,14 +23309,12 @@ "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" }, "node_modules/terser/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -23339,7 +23323,6 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -23804,6 +23787,20 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typescript": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "dev": true, + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/uc.micro": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", @@ -23886,8 +23883,7 @@ "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" }, "node_modules/unicode-canonical-property-names-ecmascript": { "version": "2.0.0", @@ -23963,7 +23959,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -24011,7 +24006,6 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, "dependencies": { "punycode": "^2.1.0" } @@ -24451,7 +24445,6 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", "integrity": "sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==", - "dev": true, "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -24497,7 +24490,6 @@ "version": "5.93.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.93.0.tgz", "integrity": "sha512-Y0m5oEY1LRuwly578VqluorkXbvXKh7U3rLoQCEO04M97ScRr44afGVkI0FQFsXzysk5OgFAxjZAb9rsGQVihA==", - "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", "@types/estree": "^1.0.5", @@ -24878,7 +24870,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", - "dev": true, "engines": { "node": ">=10.13.0" } @@ -24887,7 +24878,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", From 546094e9c101b30ae08c5bf17f8a6d9e014fec2e Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 13:46:35 +0300 Subject: [PATCH 04/13] added a utility for comparing asynchronous arrays --- tests/e2e/utils/find-async-sequential.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/e2e/utils/find-async-sequential.js diff --git a/tests/e2e/utils/find-async-sequential.js b/tests/e2e/utils/find-async-sequential.js new file mode 100644 index 00000000..81353b0f --- /dev/null +++ b/tests/e2e/utils/find-async-sequential.js @@ -0,0 +1,15 @@ +/** + * async version of Array.find() + * returns the first element in the provided array that satisfies the provided testin function + * + * @param {Array} array your test array + * @param {Function} asyncCallback callback + * @return {Promise.} first element that passed the test + */ +export async function findAsyncSequential(array, asyncCallback) { + for (const element of array) { + if (await asyncCallback(element)) { + return element; + } + } +} From 1a2e1ba6eec9b55b62b8d4f31b65061e691132ba Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 13:47:13 +0300 Subject: [PATCH 05/13] added a utility for get wordpress fixture images --- tests/e2e/utils/get-wordpress-images.js | 137 ++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tests/e2e/utils/get-wordpress-images.js diff --git a/tests/e2e/utils/get-wordpress-images.js b/tests/e2e/utils/get-wordpress-images.js new file mode 100644 index 00000000..e4bd39a1 --- /dev/null +++ b/tests/e2e/utils/get-wordpress-images.js @@ -0,0 +1,137 @@ +/** + * External dependencies + */ +const path = require('path'); + +/** + * Test Images + */ +import imagePaths from '../../fixtures/images.json'; + +export async function getWordpressImages({ + requestUtils, + page, + admin, + editor, + alternativeSetting = false, +}) { + let images = []; + let postLink = ''; + + if (alternativeSetting) { + const currentPage = page.url(); + + await admin.createNewPost({ + title: 'Sample Test Page', + postType: 'page', + content: 'Test content', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + postLink = page.url(); + + await page.goto(currentPage); + } + + images = await Promise.all( + imagePaths.map(async (object) => { + const filepath = path.join('tests/fixtures/', object.filename); + const media = await requestUtils.uploadMedia(filepath); + + const periodIndex = object.filename.indexOf('.'); + + let image = {}; + + let title = + periodIndex !== -1 + ? object.filename.substring(0, periodIndex) + : object.filename; + + let description = object.description; + + title = object.title !== 'undefined' ? object.title : title; + + if (alternativeSetting) { + title = + typeof object.imageSettings !== 'undefined' + ? object.imageSettings.title + : title; + description = + typeof object.imageSettings !== 'undefined' + ? object.imageSettings.description + : description; + } + + image = { + id: media.id, + imgUrl: media.source_url, + imgThumbnailUrl: media.source_url, + title, + description, + }; + + if (alternativeSetting) { + const format = + typeof object.imageSettings !== 'undefined' && + typeof object.imageSettings.format !== 'undefined' + ? object.imageSettings.format + : false; + if (format) { + image.format = format; + } + + const videoUrl = + typeof object.imageSettings !== 'undefined' && + typeof object.imageSettings.format !== 'undefined' && + object.imageSettings.format === 'video' && + typeof object.imageSettings.videoUrl !== 'undefined' + ? object.imageSettings.videoUrl + : false; + if (videoUrl) { + image.video_url = videoUrl; + } + + let url = + typeof object.imageSettings !== 'undefined' && + typeof object.imageSettings.format !== 'undefined' && + object.imageSettings.format === 'standard' && + typeof object.imageSettings.url !== 'undefined' && + object.imageSettings.url !== 'postLink' + ? object.imageSettings.url + : false; + if (url) { + image.url = url; + } + + url = + typeof object.imageSettings !== 'undefined' && + typeof object.imageSettings.format !== 'undefined' && + object.imageSettings.format === 'standard' && + typeof object.imageSettings.url !== 'undefined' && + object.imageSettings.url === 'postLink' + ? postLink + : url; + + if (url) { + image.url = url; + } + } + + return image; + }) + ); + + return images; +} From 343a0a1b064d1c335784e283a3e8cc893f70e500 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 13:47:48 +0300 Subject: [PATCH 06/13] added image fixtures --- tests/fixtures/image-1600x1200.jpeg | Bin 0 -> 21607 bytes tests/fixtures/image-1920x1080.jpeg | Bin 0 -> 24584 bytes tests/fixtures/image-1920x600.jpeg | Bin 0 -> 19146 bytes tests/fixtures/image-2000x2000.jpeg | Bin 0 -> 37332 bytes tests/fixtures/image-300x200.jpeg | Bin 0 -> 2294 bytes tests/fixtures/image-3840x2160.jpeg | Bin 0 -> 73981 bytes tests/fixtures/image-3840x2560.jpeg | Bin 0 -> 83967 bytes tests/fixtures/image-600x1920.jpeg | Bin 0 -> 10910 bytes tests/fixtures/image-800x1200.jpeg | Bin 0 -> 11294 bytes tests/fixtures/image-800x600.png | Bin 0 -> 88326 bytes tests/fixtures/images.json | 109 ++++++++++++++++++++++++++++ 11 files changed, 109 insertions(+) create mode 100644 tests/fixtures/image-1600x1200.jpeg create mode 100644 tests/fixtures/image-1920x1080.jpeg create mode 100644 tests/fixtures/image-1920x600.jpeg create mode 100644 tests/fixtures/image-2000x2000.jpeg create mode 100644 tests/fixtures/image-300x200.jpeg create mode 100644 tests/fixtures/image-3840x2160.jpeg create mode 100644 tests/fixtures/image-3840x2560.jpeg create mode 100644 tests/fixtures/image-600x1920.jpeg create mode 100644 tests/fixtures/image-800x1200.jpeg create mode 100644 tests/fixtures/image-800x600.png create mode 100644 tests/fixtures/images.json diff --git a/tests/fixtures/image-1600x1200.jpeg b/tests/fixtures/image-1600x1200.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..05bf60435217729ecd3a4d771f95e9d5708884a2 GIT binary patch literal 21607 zcmeI3cUY6zw(x@}VgY3kL?oahAOisr=@4`Tqf#;mQUykOfPi#DA918z4qE`ZMMH| z(*Rche0%rt?c2-8w~ufCem?$#M-Lu6aNyuE!6S!{9zP}~cKn#As5nqYO8lg>gsA8# z#Z%I5CF+wV%ubN=HP_s$O(*em^gB#lrud!2-9NWB=6s z_kniq3jO1tf83=44)bz{6yg;E=mYBiF4FF|T>`rVb_whf*d?$_V3)uyfn5T-1a=AR z64)iMOJJA4E`ePFy9EB12=EE`6bmLny{Sn}@{)a6{wr)O;O9SNiNL?aqivlOggV^9e_b*p zN-E~+CYuPJYi`{JxURp9{F$*a)4RnqS%EL?9lu-`%-jZq1r)MPdK7{}3oXC_qIva>(nfn^%+pK8Yf|bZN@!i9@H#R*Hr3cbFX(9Hq zV~(?H(zqd`AY1Uq`5pPc^lJzx#Y!37N>Lz}))KH5yxv#vHTF;4oFTYEFLo)LTq@C) zX;?XqW$B5{7b-{&Ti>fF+N|tBd@R}qcpGrgR0oBgv9!gdri|K6`x6^rKqeC0_dy#J z*d$AdQ{3t>-3C}x|AFfN{v7t*xQx0?=1a{^HXkBSQhKMBG##~9jvSWqk2;0n|5E{p zAvO$atl0kV$i>kQ#&T#=UEQvUZOfM0GvL=(@tKZ@^hc7I5@1iOE~8KCsPR5TYW#|B z@|Kglq{u5sWunGFha9$LFKTO?RyJ!cAo)cidjl0#-uU4l-FM=}h*O*h)Wjl#!~j z1p9>aH1tOjZGL~~CAO}4g-iOPgVEvW+#1FLtYfpXjg@7;^$8WD_^ZR6Q4_KRn~_BN z?TuhvT+&N7g+j{WHo!so{>EiRv5R3f;%yG*CMlKjle276facCv|3MP~(gNNQewmuU zgkWDFb>R9dwfS{(p}{RC@~yIY&Usm#Q_l`ry=l)UbEjSVqFr6|Dfa;l2~J9Oi#yRG zQXJxX=M_L^W8YHHU{!SUQKQvElg!${ZNOuhnD0{Yqr`kRCIZF1f}&^2qm`R_Mop;d z19A`vQj0(2M@aWJ;AU-kd!c%HTN_y`eQtk4V6a}9EF=G+Uq?lL@6#=z1-`jM--eXi z7ati$SB+tsH!J7aawQVk&w{QcU;!cg$McR;a@h$)WPs3}l&FO^ju;&!^Rv>#_F( z@db#;t6sECiG0cVpYFHbdN1ZywrFp9gVuP~-~&fX`Xn;ejL2BD%?NZ02Lb&&maeHS zjMphXuhX$jEnp>CB8+7>H0rNbr=YD=#M4mf15cu-@73Py$zggL_i&9;h4#ZCmjKOZ z|3|HtZ>P{tyqOqBK~dDH7y&(+y-D?zWV5JBWL_`Ru8Jr7gWW)If0WU2h3R6T*?{%J zvm<6$C7fC*qqg|z03q27Et{>!ax16FFfv<@@`97DW9=~Kr%KxA^zVnZn7N|fw zRLafGJ(Jx!3?RH&Qkb^L_r(5G_j@F_|GO2ah@t_<(>OZ(R(9_()QP2apum{Def8yJ zGaqx0=~toDaFJYZVtdM(KNTKM)-hiB1ZK1+gY8_~!yRRCnN;^8>yICkAY4W&FfOB^ z)>7$@F5;thIU`5Z<*f4PKI>z}?lgVArqwGZDifXo2J22|kG}XiuqDoc9zg&@abF2u#Ix zx~+qgq8(%8b{seRYw!%HjDdMQUFb}pj0oi0D%jw2&y+|^xL4lx$;KthwX|OulviEShVM7BKrOM966(%QeHOP#VY}Aycmz{+y73MR$;DgYsjvQcnEd; zsib4bH&8p^y{#nbT>G1;(53wOy<*ph;NxFlZ@e??HeNpIRin3bE{9|{OnK8jMwTfC z%KF}O?;xpmgVW}p$G+@#>X~|j-B)E%9$7N^+;Zmb$0?mCg8b8=fyFk%%B{8)Yf*lH z?s&7Y^-M%cVpj=w{X8T2c<{o2oUG&HJH&L;nq(kr$0!#FKdNs$JVJ@AOj21JGeF25|h7FYBVh$oDs+|TdvQ&hOm(~MU zNH6RN!JBR-g2j^Ahu69>6|?0bAMSOD1%_pY)ha2j;<7G4G?&6o#QY1Z{U6_gXvW2R z#+GI3Y4OO)^jWK# z>(!?8{K>KOHFYiewRH;n*B2FD7nt~vFK$?EN;j|**eP&_2?Qm}z>sBLRD=P<`;)3i zV0uth-Y@SQLdrLvNM0yauN4GUUpE$WE-UJpD__NHhQo^bau`wOZ<;0Me2*AtH*i6& zsR{|J>b}&TxRtU{kQFtC)@@sIL)_F=04DSbd%7EyPJ?XdUZi9cF)v!sbC_?iFT1YZ zJ_%}C^o&iuAJS^3JZ!IMs3u+wxlK+k*ixO{i#5WLawrtRgH3*2S_T)mF0=P?l3(W# zpEWYFoY;*O9X^;1Rv2!NuyKAq1uG!sigkh2yFLO*k}peID)W1{0aWdJrE9}Fx(bDB zlFS=agj4&vP8bJATPu(;5>`t~!QDx3;Tz(t7P(*C?V&=SB zOLNX#hwD>PN6{`d&Ll1#%Mw*^j#XYe{3=e#Yf~`=4W%B2;uG*M6@*pw%#N;po6k*A zv+IyA56C^2nYcG6XSKmev9>9Ek%>|&WDDPX*rMcl+ zoLD8ayd_L4r0LFNP+AbxlR=^77==4UoIMEu963=+5maz#^~h0>n4t6l+**w_3zI=F zpA`h4p)O+n6!4GqCXYHDh-P`n@48oN9sOI!7Xorq%DNpmVXln0l>)Sz!voWhE^5T| zrlawmMzMJ}5?0{CNR1;fJJVLD@B2g*Q>&`c2I-Y~Dj$0l?iO*HXGo)fhA~As=&8B4 zlgLC0I2HP+yegiIGS|Q_QGjB_L2~Oa8;+C+s|pFJs`edCo!(kcs_*5y+}&;;Ew<(x+5^U@^Yh!E8mQUkBqNv-t z0D|A(1?NI$pGQJmE}@Ui(YQ_~exfWs_@pV}T)3uA6O-31b;qE#0ckTU5bCehnRnh~ za+(%CtW|g&LpgeHMaMqabLSn}-dU=ZWtD}?bV`^-t{Kcb5xiFy%%>bWt=Vmb+?Z@? zX?1=KX_4bpvdnu5a5~c!-z#{nXSn!B2ZT%fED=T9285fd6X>~*++x9){+jhR$jfjX z^f?U+r(rMhr{fl~L>R8fA-_uSjtP5mU(wlXO( zp0i=EJ3UlAK^zf=(3oE5jOB?PH#?{5Wy=jE>dYmzzqAKZBh}oesJ^}y!BNro#CY-V zIW9ipvnkdLTw_ZQs!;FqXaQKH>m%B&QB^X^vCD4e+lCfzi4eC*yaezxjusYG4TzMD z6|X#0>ClSm4j<{~xhb&8G7{J8HG5Ff^2FzPq^2ovuX;bc9s z0((Wz%_LG~Df7mGUsYgldqoc#s`O|XTsbFTGQ_qdt{&gAxy8H^vU#g;Yu`2?)Lbn`r`+F;Yz2KdAaf`?RRvKbL&t$NfImdR>J4}z?#A2#bqXT z0WQ_LU?5rS<*P(Po8F^cng$c`OCvNx>KN&zVd0pf+`moHQ zs)sVcTEI$~hns&mnS#KCC6FY=#3!KBI(OI9zbUjhIi z6|^Hz&s#{bRQ}0CdCFJ3*@zIh^`}Z6@Niq5Id|*24TyW%y~6o?j1)6R z<}1aB7I2)R0N?y%9i>Y>XM|haYL9p?uH?J09{G0my#y0%Nh7MWml}*Uj~r19tDykP zYz;VW(VAB%9S3j__wr3|0`|Rhzu+nWAYe~9(xN_KsdRhd>x>YS{v|)9pG}gtSo8Ya z8Ww41%=;eNkY1%dU@94DMG{?xvabT`j?_aUo1|3LA-CGT?%0Vu) zd@c?dz$*1(>(;}e>Cu7fma3vSK9J?15%M*z=ao;`cXQI4gMpWs(^b~K&U8lv=vktY zlsIK{Dr;p33S%kHVvU|1f?g?TETUL}F#|u^(S%1pzro685rlT=GZMp@cx$1JZ3|Z5 zHK~B%#igE86t9XQgVU!c*Uz5(=M{ke$k92g{?aww+fz9OY^%D#bj`T1I(lmJD8mHg zo>#lP)SAfa3;*oaucp>`uQrlUzHF)MLJK@W6fn6vTuHbHJs5z_>SSQZKfDoJA9=VVW$;s;1 z8R1koxROt!ATTqvP(fk_79YPZZt)r zoCQm_pw}_m0Lv6?g9x%(Ikkt;O2(Ql6A9J;V3bHBo!G9g$vDP9aHR7W#!HSy?Z@f$ zf^f@s$&3RHT=^9AI7c22ss+Z=C2zuon9P-OV2270649)0`yAVtTG`0A+?@K!XWfWJ zU%!^XhFWZSshK;Mcd^TZdz>uWpqdHD=Dmj=F0PqOz{vTM+Py<_ckPwV)I-C2pzCYl z(y5j0`wN25gXP8W+%uweKVDU|AUS4RCzA3+QaVjB%0ay4!YW*m2F(s!-rBH#q#?1<(h_;)w_PH59qK`9@S5X&Si=z+W8I zyFI!5aHU|eHv5GmcbPZ!><4&HUPR#6GlnU>Ifxm|Bl`{# zj16h(DM~iEMz;rxlkVRHdJCZYCu4(HxZaKw*1F;* zCMnv1?BvfccM_^MTKDkQ23_i!CRNKK zaDfJ_tTIZO`f)#Yy3Vm$U3;PhZ~cD2od=37L>cN$X4o{CF_`Y1&`|Z&>F9+D>CL&- zmZRu}FVSOnp`6Z*())n7nqV#O&{}okL~+ml{bW7V@s~Xt?`YhvZ)L2~i@uN^7)AM) zce~Xgn0VE(r$d>s_T3{0dOb`pc+18=%i%aOd^x$-m;Ttg;k$lSJnuSn|57Khlr&cE zpY}Ym?%P^$&E^V)8qvzZb(LhSufrBS7JF?v7lBgxIekYDmdsvoP@zdUbQ&2O_sHeB z=|}|$C8~};(xrZ_GXIQ*$fqrp#L)h$Bk@#>l4!~%5xN3}y9(>Fa8o9=`T%cucodLm zB6b(z2rt$naJLiRMcVn;BSLa4;6_>RS6VJ4`}Hyf^ymLYIJooXUZX_fVE$xz@RDn@ zRIB8?$AZJ0__u9<9EFC#9%Hvf4b((lTjlN1wv%Dru;lIq&&AI@fAV&wlQ5}}h%mK7 z^vUW*fJt({sXLywWd;S&Q=FFqv3=Zp$E#sA4FnzU<-UpD1}GA!=$Zg3zGSPNyO3YD ziaDUa2eQ&`u?-+fWqABHe|8%X(GB7Ft>wmWg}S#;<3A`r)#%t^HXiqgfmwiF72onl z0k}ai8JZXYlY08vcHM)HYmz*M`XrLe(p`!4T`1n@qWJi#w1)I-1H`#8E9iV+Xq48R zt^VjwEtWO?1bjt)@2OTj=KT zKkNenLP_N=|6w28AO5?I=S}ri9#^V8+kn;|Ydw6pK@h&ap?n?Yij1|Di3O%Pg%x@^M16`!b^JVzLuqYfUmy8QWbnT|bm%w2`Xr&n zp>y54^LY8XPWIOrr(!5bK_Bn&Tk#)pp!V-lmjG!AJ9)5E2Z!PVRfx0cDmS&9h*+q_ zN;sl2!BMhHS_!$yvV)YRHXY+LJ^_jY>z1!ul-uh0DOjc?brF!Q5KW6#Bk%OAY9m#e z=9{%kXCi`3?H*vZG%Lepqt3OslF}-tmeOB>ALS;4D;Tp^F4@|_H*yDZYNC36B##`# zJKz223o4nyVeOq@`YwwbmArWX0PpjrqAm4;@H0{8JR{$wMPOP*)3yP^GKI4%ykv1oPMN{xZ9KL^Z&JK@)Y!q! zrMpKuvq?LunK5hGAeSi|l|uGduY^n8ht~3PgBcCouo_jpWV;XHPSNM~7H~}kOKYi=Hb8$!&<(^XsZbZB-yvFc-QiX=psGk9ES$(a0BvU?Y7nFG_!bVx;k;WXI7 zKF|NH@aM?iLnJ6c?)~Mre;W4x*liewVxt!$^&}r`MY|b4;eg|pe*M7N1|&~SE@`kh z7hI5Y24O!B^C*tMlX5=yFk#)aB#9NS*+-HkRNk)nJSek+b_S1;^zl>JpSX$e^GtdA z#q=rm8;^|>F&44l>f?`l7)`CIS7h?Pr2ww2N^TIj+NL(@XUZL%`z-(gWI;O+hHG6> zU#B+^ikGuXkJId@Nef9cwXhinMo_h|zN{7-Sa&Q=LTH zxXE|qCrdj?Ddp-Z`Bv=I8TW2rz?$M`%YH-C2P*|AHfx!rAD%Jihf$WRXOB=oG3Hp`8hd+JBufS(Z@*gx!NDr z*MefXK>m})mpiwfZ?|!X>vZ$jFaE*v)aqcHI9iY=Kp2?*M#)=c!p~CAv-9l8MffO{ydR$+F`y28HBDA zOJf)Z&_UBEX0tPI>IW*U+nbu$qeXo}m;T1YHfB`VnG30?sC38?L{b*Av-rl)dp|5W zA-W>G^kTYOePS~6ULn%6pVx|_rdk*F`t^;N zSinLu&0uun5={no>+dAtPHpSyRNF}goKF?$OqninpCRc2SDPXR__&x&*og&gQ79-<@t66<_4F_Qr?P)$`6&0ws8 z2dm5hz6`Ml|C}X>SueCy6dNNqdlZD}DL|kPG9twOmOPn``EI(B7shiXg8$JGf_5CC z%mcS7Te1b$7F^W^%8&I2T2aRF`Q##yaG%~FKA^&*%tKB6-Roinh|7wt?l0op$#NO( z*KH+ukiAT$^jR+?dvmv2K`L?kBGq?xTdqz!@lW;Nf>M-Qw;)yOfcgEl!s$s!oC# zXzwp;#!pSTiK(n{~XdWrrx@IVdP32Lywm)#>d!D1>Ata8I?=RQ#S{{Vh?z0 zh4WGDi%nG2rzVE+ zB(wx8hbfA}TgXbBsIv6ih*hh!)#{MPtj@*UXy7TV^mK;&PJT^PzEGwzg_&F?{M>P2 zKmmQ$qmyzZiL2(9tkUMDwhL$q;AW_uv-#9_@9<7AbIQQSE;d1)e3O9J$AO|%<@ zlPINc%G645q`xxnDU)nr1T^$bL3A7}r`CKMu(tXl2@=rNYxjFQjyTi%40?YBinn&j zDH;4yV*=VuTJjdrgfdjENq-i=*-uGa>=XoymCi%U(mL;^s15_xMyj?8XG51HGn^uRQ=7>X8?x zSM<~+Z;$pS5c9Md^EQ(x-pMMKmoLz9gfgU`I-0se`rmGi1z*OxV5RQuB7M<~49a$`4{!4(zcZ-<0 zG-vb0H#G=T6eQarGIQ(P>VcJxEF#mD6Zgj@p8t@!VIHZVi((dsO|A#u9(%UD=)OrHh+ElA9^T zA~P(BiOR9gi>O4tJ+Aqq8)i0-WHHOc!11*B<)2h4yx1on_{!%stEYV{2r`WP`3oR2 zKAl?^3eY24FAOQ&pa9|FRD_|I#Dux2#K<<_sclu3w*h0OP{#>_wbsyd_uA^{3}}_W zpNL?tOIHD7c;1b+7X?*aBR{BNjUYeG;KN4-d2SvE`Qa|R&}(|>7(=x;!c6L6gphnf z0$uN>-~&pvXK*X|ak-rYS;v{^vLSQ!T@%&LQnwDP2HHYeqWq8Tam^duP_bE4Ldz5m zXvv)SP>xDK`E4eClEOxVkoTcC=l8zn_lDi{ah=U{Y^ zf`D|BRo^?0j(|*y&IGAS!o!`gUrzSx6F$;@FVgYP>}8cgagE;s8~89YFLFm-G~?z0_Nt8Y>I9`ixV{-fs`p!tBuJhuWLtAys3B6Hq6 zt;Lt~_9R)M4Kb>)QWIsVhoLvjUyZH@I;mxN8CK6EB3K-`(YP42>*&l`t0imI!9h{F z^#)yXV5QcQKH=ajDHt&Z443QGoBbKUExI@Ml0Bz`zGRFbxyKx6>zjaq;ejGQ=d9qc z#oDnHP0aM_X8j8O+?g}d&miYwzE22`S(*=!Y@%5PQGnPh1Mw;I0(!;1jYL?sApa7T z!i{lLhPf~D{&U(7=FI_Py^=bVLYiUB+G<3|l~><;0|4l=Cnr#sUuTLZG#`&om@WqQ zn(>S&_XckPFP~nc5H`K*@BVS|J|gjraX`DpN%5F)H~-j!#yNIrKrL%0jh(myy~g4+{0fH z71eAO$>{uDx>c6nSQuwdjqfstf z7q@O*yS&()Wa;IRP(YGTn6o;$)dwfqdm0#z)Mp_FQAchoKFDRfXsnom$La<_?cqQ? zR&1XG$Ib*UTF_=ImuVc_7!pKNJL!YS4P(6`qo3-4xO;Z-Q_1jtE409wjD81O>3p0G z-IrKpFF!hS1d@5@%TkTD+UoDaXYFvuJk>4|^gv+f^=Whf1I7t|!f4p<^+3I{U#%or zCc1hw4IQxgW;UO%y=+=Tx8!p|E_l2MXjZth``$*z)Ra_;3!z|p}A zREDHu>PT^VRKXJ@)K$53{2QTG^S1f@;s<<9f9)OJx6n5gSSaYheD zK9N*a;B}_@!Na1=R3cW^Ll%}Gzn`qqQ`eJC6+LX$k~a1%EK;%IZ-)GDU3j6PT|;&R z24ys(X--H;9aHqx2M`<4)w{(qSt*Y5T6OdzfnELRs3pf#MsvQ7C_{Mb=GNEMf*6rOC1C#|bj{~sD3y&0$7PQkPFB%w zH}sOSk_f`g%*v!u`v%<|2`o#S~ttpn?g>ck+{h@U z-}$fR-)DzTxI2heTb4*dm{4xWv4Ny>9qIRRgbFxPy zdeX8S!kmk{aar3KUMhapZa^J#l!cP3jeYT(@U4@{xS`XUFGKSrIy99O#>=M`|uuEW`rVb_x6^1fsY5{tu{(km>*c literal 0 HcmV?d00001 diff --git a/tests/fixtures/image-1920x1080.jpeg b/tests/fixtures/image-1920x1080.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..51da15e54c2b62da38f700854054e3a704576bca GIT binary patch literal 24584 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 literal 0 HcmV?d00001 diff --git a/tests/fixtures/image-2000x2000.jpeg b/tests/fixtures/image-2000x2000.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..da1649431b8b9a76fbbd4c65a082f47731b731ed GIT binary patch literal 37332 zcmeI3cUV)|+UPen)UhGLC=zf)Kn4+!A~om$q5|e10@4+v6M73Iz=#deFapv^R7#YV zp$3p51DFAX2q7Q|J%kWK=mA2#8$I)#^WFP>w|vjJ&%J+S{SkKdW@oMSd&^$$yWYL^ zb&Ce*0eg1s-m`nxo;|zw2nz1myZ^}k{rmRqKX&Nwfg?X2JAVAfW1^yB5NS!VlTzZM zqNmQCl9G{?`&sUUq{0P-vlpb#%AMW*5dlF#!To#p3-8}Ad{#_U?Ck$>+xiFy?G^kY z_+_WSX<&ztz)m57ttQ|kAOP&xDIfs+qwNvgxoh{1?Ta^#fENXJ?AX0maF4(byLRjZ z0D&Fg#XUkte^R<)Dt!8$->+{PI*lvVVc?gzZhDjA&>kv99| zLA;(H2+9?F+0`>nG7ypP)fKPx=fKPx=fKPx= zfKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx=fKPx= zfKPx=fKPx=fKPx=fKTB6Cjx?6zJr09`_jhSh2x<)+Uy8Sub_GJ5>qLstH}^;gp?ZJ z7aBD-`l5AVd`Lt$7Yp@rC`-rbEwZrH=U#2XMNdg*)vxySy{DfDS3j7<=Bix!LB0ENNat zYQ`*iY~Mue#L9<*xl)$63fU{TzDYd&)XY<8ghJ0?WI*g8b*@QHzPI#%Y^jbD1zmsY z&M);i;preuP0Gy1?YQVSIiqV$O&(>Gl$nfxwgKG>#)4WtgMrqY=8b7mXSRT>dh>b* zr?-EXH)C3B`iY*h4P!plY0`EjRq6y#&dfXR7SHlXriT2Y0z0h|vdpwabF9PI$ z$lhDNcM#b+LX>#+dDDO2SG;V@rR!V3nvmockQo6BUBLzv@cNX7R^LkkcXmkTj;_B{ z5-U`ILl)48@SH)~a_ymN$I6n$i?HsNaT0q<@Y?tBAZpp@1Z2{)9?fwVguc4<^x01L zanA<|?`lw(yv>V;R-&1s1J2_}^f`4pS=fCGAURp|8&$(x!if10Q0X2;-jwZU>mZbd zdatc$irFi+2n*$rEjsC7x47|rQA{|kBi2F5R^x4z>;`0=7Ewpk|K77eTYt#Fp~o&& z7kS3TTqQ1vP%RFD{WzYQLUu3i()Kr|qWXWmD6+AV9#F=0&OzOdi){~04n+5J3Ha@v zAIid-snx~^jdAbCky@!0ewtlHP&Re2cp0_;(^`1R_5EkHfaG6CO$ zJuEVP3_EyL{3Q#o*m^}vsPIQoR*A8t<>M7sjzyU1LdYUDL$kmy0hW|1N4FY3@bN#F z{D0*NPgx`;HRUO~Dpl|~ub4GUJMY=7)T7aktJ*hMnV^=})0~xluc5CCoo_SN(3IXx zfauekmBnlW#)(wy3BN1cS+G}uggss<7kgz+Qj_t{`Pw-bM>eHinCIhqjV-mgma_L9 zI-y4&MpZOLK3sP1VKGhK5p=GeolND_B2m7-f%nJF-CWQ-=Wvy5vu;8!>f}m|AI`Ya zq|#|pwtCY_Rfysl+zj=9&+sIt!q#KEoG?+U0C;(Uj58oA2M!MT)#A+fKC4YrG5y=5_UKicwL2J1jNT)HI*MP>foGn008~(us@l zXBFCN@+xd0FC%D{%)MWKa1y=YOteiY{4pmh!&)})9!Fp#b3E__eNVVC%SUGmxP?U7 z%PqpxnGjz9*va5n-|DGp_PoPX)_Docy(h(*Jmv)q%At!pT>b{1d0NVL`C3Ny(v0Z9 zj}nR^4rm*E81nCKcUKm(hNU`48dnYjpoyzt%wtj)q0}V&oP|>_Fb`;k-(1L}`3Rv0 zw6#~~tix(C`^I}Khx^MmEn(i3ljX7%r7VkswFJ9#ABrV(9~+%-S=~8us%%fiP(gE1 zmzn8fB+bw^q-nXS;xZ`A|EOIJB_J|&Tn%yv=PKd`t)T^>VPldZn`esBddL$R4k|%5 zvR;-H`dM#epXv#Cf(|Esf#wO*aQgOJMa+~i%R=%3qaR&z@0@fpNgEm|A)RG%73h<@ra+Ot`7oWL_8Fp0?rQNFCPFGUB$n+W z6h0Utd11UDi`pgZZoeW5qi50wYwG=qv!Wk*S$R6W2oxzvhj;6LCepsIFTIf0lTAEE zdQD1(r(&0=_3DOz&G8bmZ{w;}5FhQ-xwRBE+pz$z*S<$`&s1RIvE5k7G?cKgkdpT3 zWdK0d=HF;9R1$d#%Ja)%vF9s`Uwx8wMpM}0<6Y4+NCT{mr(;+9@2oY=>OvofC-0-5 z5@M&VQ*$*^y1J098~EDu>Hq+3GQlP4e_oY@8(FU8E3u;x07L;7N`VvNWW6yGsL(Xl!M)!EdbMJppc(&Nput3xYn^ln z0PIj`{_uG;<_innx*%Cw6JppWIIso8NF6N1(Z&_xH4Bp~*L8*+cP6=%c;M(O;I?2RGbDF)a zl(&E%&rfdFtHjv)$>asue0tl@>q!`6PonXp6pgz(IgW6*XHB0;xAjAEK3w|2!rk^m zB1wb&Toq$m8!+!QTw7742oLsHcm^{Rhs7atPxX=~7O5UhcN=0Q6-)1ow})BGwQ^$( z9}+LU7Jt$BWKpw~bk6jNY|tE0@spOc;DFjX%{$MRiAHhDf~~bJ!e2IP{>)a(sCc?D zetiBF*3v5iDEhdkhn8RQ#O{eH?7es89C~G46s2I(MaW(#%*ud0|JgaNQ3D4h=A>e( zo4Qa5tvda`b^~HGbWs{a)b8rdRzvl;6Vs2J-;)x|-nFEwR$D1*kKgiE@A*8|n3c`7 z(9YRF4M{d115RoM$FFj{6`)WWNe;Vr<~JWNt@CzW3*p9evIW9=y?Pw^liC-KwStJ_ zg}b;L(Aum_9JQ~DHOC5EnH|9!LZlM)&K^|o?tR@xN?u;L23RaAsmvfK%OW^wW+nRBmGLgrA2Tr7KQTTej|`o5LBIaP zcf#}B%@Z^ypDz|Z4s$0Q6%eztad)*j8Cq{Udt{}hOw;Rn(SB1;9Lt|I891Jns+PQb zuiO2156{l-d&GDs*U=Qd{Ma#tgY}MKK!O{UN%_<3@v|bQUiv-m6SKSR@q2I5IWki} z#D>eudM&FBsk(`~u4!ArOg?}p)!}YHuPKMP_S}s2Ys6yHgWr`4lg>Gv+&b~3;{}zs5KR4AeWzQuMc5{l8rOW&BJIXLxWQreukFFCb(4(+ydOX9L^L5DLBNKvxK_i7Sc}W#%#klr?&dn2CV#{6%tAwTc zV-KY zER5ILR;1f6sFjhBImn>Alp?H=6^9u=l!!D11ipMNlUzm9;|?s$`!VgErih#VOVK`# zUoTGEmM~JAbD8V5)tpIQuBJ|wUUtD%h>lDr7Y~t-xHv$(LCSQAq07O_%g3m z!=E8uBNkSRH^?vegi_N;UF{Ud%{`vjd-#agC0bV7-PD%cREDxn8F#&3x;R}#`Ci?* z^4ME*s%0?b&l?eGfoc8J@SqMY6T}KJFxnQlvwo>CGnn#h8G~?N`>;x{pB3se!((N8aiH`T{BNqVix-&f+Ke)Grk{f3-lJru;R0IyhbJCU{XaBH;8tCq`L(;#M|!3J_=Q$Ng3r8 ziwnGCAgX$g9)OYwbd`O%OEX{87M)(rbm4_V2W6=b)7xyPZ#5G1;vuym!LVLom zxW>IyQW6&KkS%ezY_LN1&$#3Hw%OaF1#&I{LYa>9Fp1|9jqDd%%VScpd(GF-dDMYm zxWSr_x1WU2fMk?vl;GEx)Td8VQzxH3Y`j16%s@WfKc<{nq@+Lpl)Gx(f1=`(ZAH&G zUXu>0J!UP0RII#5`?%6woZ+6Io$!x5k8r~*xM_pM9;85`dYHf;1ED_G^TDT6f%`&; ziBmh)7Wo^>KK*=xDN=*2+G54HP;Ptv98JpVO~wj)ZC$8C1Ld(yY&vp8U|>Y2H85({R|%zhRrGOm>m zsXyi8yV;2Pq+Nl?2y?@{N7GhoB@#)71b3C7r{udiGEl<#;Pr4Db(ZZNwsFw2uHx3y zT5l!%$m$d03rW+zQB?rwYL$m9*e*bQ>|B_Eci?VHS8u3P_u#&{Zf^w}0f=F)P zVjp`*Ee)pF>>BmnN`;E7E?8`Q00ycU(<5a8?!UWi0SZqfV3P&cqhU{W8Q*P;lY|aF za@0NLNK<+BW#R&ht-UJ3#-8A$uG?G&0BuHr1B9)U6cZEXNEv&sY24>pl2~59clRw| z-^^~9P8#Y2eD-qE;k{02UZJ@WwS_*BicwmZ$%6qXNe_y13_}U+s1rZ|ik9KG*_RZq zMj%I*F>!gCS^eF>(dpe?kr^Hw$w@Ypw{luu^06=CV1kKw^^ASSTG$qF{_-S<>2ys% zcI>@|{DPn!WG1dt$8T=^7EU*^Vetjl@}`~N^|CNJet7>Ezze<_)8*;wieJ@gBIRn) zXRXasz#Ia`PpL!tRzZ;jY4Jt!bp$5h*aWFGfB4Wd5u#WTru0zS_R2SLmAM!f=25WR zKXh$S6``>ZC#M>BJIHYCARs^<8IUDkLLTRcv#eM&iX`tyiO`{44IQh6`b1m(TROD? zykG3WaUMLla9wNwZyKAdwHS7L^BwzP%di1Quuh5q@EIFl)(;IS2LF)o{Icaw~-7dJZ zx$;8L)S2b&a7E^{QzG}{j^aU;`d|9F$4_fmR4^S_n9609cyG;yFFmY61N7 z{%m9JwscF|l{^t#($mu%Mz8;6L0HJ!mIsTIcCBUwiJ5pCht&ndyXKHFby!@AYGM3x zn}$O8&Fh#%sw*D*%(KyE(POmQ&iO4E2-}c)H~tp#H8mzCCMAU(6J_(urN1s$c}V3Y zWAUq-?xz4?VcSDGNWU#B2uMw32<lNonh3 zr5gGe-5NOAL&5Gt8#yy&H1FdLrR76s%K~;AXZl9aP!dV2&$(%g_O@5974oYe)EBL7 zLs)dsdu>wunvCv(cz2_kxzA>*a-rp($}7J#SR&2iFZxtt>|QY({x~HbCGgX54CBKP z`SDPO>^0a9dTM{r39bCttd-Bmgu6%TG$?`GP?b)ox8@?VS2sJHY~Wt+vU+tczaHwx zkSPY2{ZSgjJ98STuw3sIC8|c3EY9b4&}OXk;bCL(d5_Z1K}`lyv|imr8E_~-=iuVY zLMrz-B7k6+1DixwS{T9a_#B76sP-t<_kT8qv478w^Huq{`$eM|KF8~;jB92wF@aE8 zI?zJVuRN@qp5LH661t8XPKtifoQBWx>N_p_s?^vi&c~-(+CB#vl8%9&--{h77(~^Y z@@|~nIi>%(Nk1SJ8K`zZ^4efv%D4s*mIHmqUfIz=T`Yb}n{^-6WZhx1Fk3*l8yLWa z(G#QOA{rZ2+0R$S+hNnKh?6}-!z=?PE_xc?W^WzJVk9Vbj48)ds`lJnLjC!>lij8bZv>` z@F7K>W8vwcsuAF@Qeq8<_M8&9H2mU>)0eSss`gX`LwMPV%Ut>C2R-+OMR=)6Y+WTC zi?2WpZ^w3e>dfn3x<@D$nk9z63|3BoEBW*n&6U~}ElCK(*IY%(IJsrx2ekm?;1lyj z6Pigf_UHC$H7@K{+wEAGPy1r#9_%I5To0Me=s6g*Et!916FeNt^}|u&Xju|TXD>IH z)JB~)Zqf&rppOEY(&IL>DyiL=P$gc<22`0NcoqmNbXj`Vqd^7DEu;`q4->N!Js`A+ zerd&Beq;O7>r4yAi5bc224)y%U|~u2wK~!%;Z2Esy*C$Mk8S9`S~ zdvFx^!NDZ1#eL2R-Fi!Y<(I;)Ufla;hm%d=J=>OcIJv++sqll0hS9|SG;W$b1w$pt zA>iIY6W-RRQ>P1D(se#|kv;k~ZaFtaV- zSoKG645!4M;@;Gb5fte;@M*>@>+( z;m*}Niuwbs%EZ#|c3Zy6Dsd|5q#rcT`~a^EQBWCe7cYba)&%#M57OVZzwV~(d0SHm zNq{899p6)C+_atbn@TaM^o)36YiU$acJ;01d&KG%kauKFSV>7qSs3DX;Rko7G#i~% zXJp_GX7iL=PYZQGM#Wr-W2(HLe3UxPWah$5ajPO1|XetdQp2&qG_wO7UzyCl((#H)vWl z6Yi7T7#euWh7yIha4n_mt9ve)-iX#PgE$sXISaN?<&3PuPiy3bQ+>j%2P!cBWtZdw z)i~zg_0A0d^;UiLq(R{jvJ^V;@Yg>_G#7&*mvA|{b4EqrPALZ?t;EbMX>KF&8d5+uFQ4@)Kwg<2N>* zS=3EO{wUNnYP7iAZo9GR@K9gl^%-&DINS#+S+e1o>yXf#VHaj6Ugu`f;IXIcu8X_= z+@^GOg(+zSZ%jzG^PgWbhP57f^y?=PmKVZxids6un6n(d=su57xO(m-&B&mBpOXMQ z%Qh$>X((Ef`pu}b#f*3+=TC0rS)l$TNDQsFVtaLeJAHZQ`DDpglzYUb8Ig5oPkDv- zS_Qg+B->N>VZj%$Q!!eSt~|k`c%IqS?6$1tAfwULv~=xf)1}VNvZke`d8B}&F9s%8 z?9N;2&2d2Hm(4s-?4l}4x}GCepE_w-Xoc)gil^pOtzggUjzZNIa%8vRLvQma&Mk@)Lw!FYz2M>wH9&xh63^B=E>{2 z5ktTI^m?bOH#+=rl5S7$!lUf`U>2wYt{d=3b?eL9lig1YN85ZNY;fz<5<XM=$;7d?>LDGmq=KRxX6kEdwA^EANj0{)Q@df)>EI3Y-Tx4!^Zbk0<78o`5_f- z@9eAJ3Rk=}X3}8nl^cKVcCIDq&}}wXhtdsdYl#Zq5A}BuqO$OIx}94<-%+E`{bAhB z4atpP&u`B_JVGIEBid{Nq(j+1cW=%M9H$u8xOelNWfbs(5gZd9oP_i8*K=deG!|5Bb*4KBYdlxyN~*2g}4z z!Oyr9<6CmV9%E|~*jwc_20m_uZ##us6(F0xApk+wClxl+R>)lYz^)!7JA~GG5FTsz z#IBOw_^$0ZO9%OZGx6xO(>ea?4lbF&ZrvX8o1zJQy7ow&>tjKNe*<gpKxkX~$ARC9{+r*-x9d zI0gJ5_1Gz?IeRm8ok0#zcR@^9!&ul3y9*%tBZJy;bDG!JlGe#*F2%{N-;9Sc>Ms~X z2^u|dO z7a~{RYIs~E4r1G1B$#S*Pq@y&#y{%@3iC#OIYE%GaQ&JD-N+!7FPp=PfDL+SCoK@#_;MLuxkn+uUn8+T&!} zMVB@t51y=$%ToZq4$cD7HHyD4On3&BO>&6nNR2%=MZeZ$m{}F#X0-h1*nAfD#%=If zph~>WB;2ik{A~ds?Ylyhgx#;LYi5JN_tR6r&htqF2XD%U+RF}>zdGGZzCT}$w2~@W zjE%T(APSr(L+&pRo@+xax0z2ar4ROCXfO?gz{O!rfAZuE-GewH zyr5@Rw~zRRs^GrLb3t`V0zrfuflC8+&>neWwYh&^%bhwci*Ne?PkFt9KmQ3blP?!l>(MYEozt5iL$Wp z7W>GC8@&Uh(L=`p_H2%3_)_{Gn&7JIK!LvS1HZ-PSexpUT-2Q8u_+OPklCABw$#kR zx>I@@XYMidF)wMzyPWVLxuHqm=V2}XZVxuyngl)?4Q@&7ZTT{QzrMPXt5Y)?aW`{Y z+=nEO)3QqJp%k{nX5=n`OZ0+F$cH^pRPeXw)fCC{faW&f(J)clY;Wi(lU_ zxeHC--@Y4c68`p;EYHDCYYUCfpXZ-OZ!d6aIU}v{V5Ps-5sNEh|j)nhs zF=tXKr)Gte^<_9}XK}GtYRL8SaaU1HtsT^sM|!9d0uhDp$^EJ-!f=~PnJNqYsQT7L zMn*P~c>fRhU*Yd|bZi7h$B`;OEy*}KI)a;8#yhA&bti_hEJeE53PSJDdG-X>qxnbz+H2wvEpe6e7RpYENrk#Rp2Z6e%_o=b${(v%fAs3Ut z92${$^$6Dx2Ya0IdzT#gW$S5yWl_z0&9zEJGIgf8YsU&BbdUIc6tsEdP97?&iz(Xz8s$ZH4i}(wM&Sd- z!Pr))+_1d&8Jr%HLL6eQG#RB$`=LSQi68QQwXHmj0&?5RGs&i3!~PL@+v?j=evp#7 zscj~)f{l{B3--M;=9B2e6vByPT|C2_wPe+ck4W}r~=zhj;`0=Fw?ESuoM`hI1AIJXo)2W@|_X&ofov>9Z zk*=NO@xE(p-nu{o+B`b+uyDIqNg0Ix=OsP1jepBn1;^qhvRb_mI&9v9d6ny0;hH`S zWX>9BY8fy&&Z*1#r(%U4De-h-VWf%y`S7vr4fTIr6O?> z3sg;`Zn6my8moh;i#vM{ctOqH6!e;X1|44nAs4mp>Gqh(gT5P59u!A#-x!SuqZgfw z`uR%L2lt34RUQ}o86q`{D6?LP@suAV9|!PI2`1XBEc=IRn)T;zj3^A-Iq*KklQ&C> zr?FAeA3>{+*aENsIVCo{`~O%`E!L4sqZI`6s`l zBwf00IVHAhnsL}G`2+PPnzh~s!07FIXw0G^a`T59#Ucd;PKo;dPX#Hibt9|LxqM<< zA_7cD;)--tQy%$sB)=(WeE)R8-!cnYxgp!X_fH_nS0=)e;yxZWetK?d65DZ<3vaBh ze>1&u(He1!{DqJgIWK)b3Y>NRGPv-$-p|!|i)b!^DO!e9-JPkf?1WoCui-glb>g_N z+wvEHU5!z*{=|He5>4saQV@x`&nCIi+TpF&S9zt@z+$yvSG9#26BH!8*J*ln^bKWb|0fM7b}7qs8{bYguhn>$c3X`hW@a_Gw6 zZ1gO>C|66bM4Jk)2gP9Zm)B^Q0YF$us3Yw4ks?hJxra5YzXc>@Q&9oBZ!ZoEsydkT zb5D#SdU_ZREcCl&m8hUlSHa}L#m=_8Bo?VeV-uN?UHWTa|IB-eaghF1O;TM1ki0!@ zFx@=3z1;z36SlK=d8fbWQJFwOu=al{PohkRbSg73Nag;faFalDW!(E>NA?PgA5;3PARi=?Z6_tbml zs>b`d$_eM@vx9EE?7PD&0|d<+ss7VxXw!}qc_?aAh=u4=%lMF+m1Q5)=s<57nTWg5 z*yUdAt^)2Cyfh9%zY`odj}=YcePKA;3<7HU#cdJoCr36eqL`L9ZL?ZUvM4%{B1w6gLx zlN%P-wtufNl(d*hHcyhxgvTSovhsA=1j8wxVm-TEn5`QUFLd+5-dF*E^txblJB69T zNy&}~m^BhFI?=W9qf3Jo+M-3`*5Dv1ME3TPO|8Z@wPbBWxJ$wmJFdgj;8Am$L-tgk zOL50nmy3p_gn^6r%U~jL3oslEOqD?x!m^<6Cs(Rwij{?hg}CExilaC!_nKUo{^`))C)7MOW+F>m>9} zk5ASxh_;n@^jrs_pa*qpe~L5ZUIo@H8LSzJh2)k_ISRPJH8v9}+)EaiYDDo3RKkoo zi?GXMJ@<)B8ky-xP>=hdi`Q*B`ZoX&JQ*9ngCv{_VSt>pnFB|s-ed&i$4>gPJaz8S zaXz+7;oy?~qkubSB_i$(d1NM6vj>HIHQtc3YR}0fwq-gFXoY1JI&Vw*U)2uj9`U)e z^x5vfKP`$c6@PnMe!IZsV~6VC!X8^*BM7vDKqM9d(y|s7Sdti$AQVI$}-g& zk4xH==Rw#@2lS~v&=mBaf<}+kB(qI|!l;|$nk;lgeJ)Be&AspI3&!XGMDzFI_Ru&9 z^T#!F&qLf?P>9IOM!Srbh#OBfLpE@nxV6LUGiz5AgcNC#OOm{yC2WQ6lLow;2~(s0b$ z1|6Tq5w(NfY$KkQyga4>lPR~Fgt3Ubd+FDl z!T}ZQpFcCZZz)LLlFh8&yQd>dO$YkJc)MGXrlCfvMR;xrbtBl$V71z8ocJ(AFFa!C z;&kwQU<@(0VBuK^jePzB&=M`OFrItPJpF#nqN7yP(VKfa1GySO$#Iv&1LZc%Xw&Ot zwcOsU+-SX6*v-1<2r?ba!wIyG+Wkll&L}SkXo*_}OOaXa6oFfZh{Etv!nA0bWzvBf z4$Sa*xVW#V?15?1N;ml*w@V+N4QeB0sYNu+gD&txx!`UJBb0+?#qHajtxj_law|`K z+7?P4pDAP}hD(3l4#KTsVrHUH$AiQ@+uPZZPRYTX{%phm&^x4X1lN7=l-T#X>q zP>O13W55fGylPuDX6ykT8M3qib(;VN`W6H5{l3GD@y`qOZ;Pp2H$%1HnQHMtR-SF= z-4+nbmR#Nr10f;tth`eIqUFXI(ZgP&r&CFZel&miphB57Sd6elC!CK^8qj^v1@6eh zGg9)4njN&n1O4?wdaF@UkAZ!#-P5MA(q$TjtprSx23SlY(cN;Zsoh1UR7t5&Jl#gW)}BkWD(8q4gnXWl3iAym1iX-V z9Js<+Tc2yopX{xR*u!qBHc?QpQ_V6>|B$t=#Ky)8<##hElZxp&<9%Q`)0Kw+3SGs3 zL-y$8c4Hw9vv_7urM3>fwe>^@J7kQQRyu_Hv0_4ZROWNSRZL9NwJLGmY z%=}yE14;I1tM&*x#TZ0d$q5fJe5=Jc*VuH@VgOfkP(quK z6VA4`WqxwG@>3_v&uwwB0asuNL2ahG7$|;HiCIvwNLd_X%px|5w}5+KDf$-RCjC}= z&1ti73((pm|J_x+PI{XBcW(vzyQ_L&txhvM;!Y697-e~BFiR>hem=K9oYFvEf1Bw| zPI`q#$gQ=8(HF-jf%k$=F-v`4yhY39+xB<| zbfo}Pf?g%50fo( z-nGYxquBbVX-whfIockYaxcY;EMC76akqyK=}@)KWBJlB=aiYoA+$waR@BY_x6Y0a zevJ>L+RLk`NO?%13O%}_kL>PhnN(9U9;YT-U623s=-H=WV+i%Hf*ZT9T8wVZbyUQ} z#2p7qUy`T_!El{5cW+bZKa8`|v#{Admgiu}o#m7| zO+bd5sT%#;ZbXV#2JCu{@3fg}P0-alXg_HEHEBJG11qKEoM?rMmY*tO!fM$!+VO6M zPIaz{JIRll(=*%_m7^i`kr)j_#e93-%1QiDca_BQz@8UZy(bEI#h`H>{>wOX`@lrb zwsCT%tZYQ%CbaCu)zFrVu6iyEEV24-nhxJhGY6U;V%Q7?fGd?`gRzkPlb#YTq3q3f z8yZsim%_hXr4z;)DCEtbjhC&ppf||U3h1SrQO_`vT+H-u2%o7m9*uASu{w@z3wvwFydD~qU5QAO`yBr!BQ8yrAsD0B!g>>5xuH$fqWLU{keHBA?%^8ot zLoL>|u2dWfu19>C$cI|$z(ZFPF|X=jZfZfRHDM4LldJ9wYeQEgDe#vP(DmeXGe}8@ zA?fN{1B1&*TCQ8Vq29sBXmOZpF4Flka8m5xc@uBE1oi-;7h}6FRd+>h81#QUCHqrjM@;ATquld+%i0HjKL~!o*2lMK;Wb4RZ3riU- zSk?LQvLR_)1~r^~UbF1e01h9>U`{8V`K!}wp;FTMAMR(v(!I<&bjCbHAaaf<$I!vYfcf&q?w zJ$#}~?O(80K(E~$u>2x_4>S5rlBS0I`U$CudiBK}Whd8id-G`i{-m3MsbCyhRPse& zl29J`xF_y*P1KsQvi3NlZ5V(OZRgS5aZV!z)v=apb+V#|zT%t<=cDe9WTpl2=+Llv z(8q4ptc2B=O`uI%HQz8rH64k6rF5k7ewx@W@AeF{COj>Ni|5MLNnWRx;= ztZ73^^*O9x$#yV{mcSjHbIo>uWF99)MdDD{H+4q zuL>`UmY`?V9jLWkWqYrZo>lg`Uz{kv1U}oYa@S?F@41&K`SnhU52$Si3nkto1eRP}5T6&4KW_VzYZW)e+TNE3c)tDmdvLRs zf=}Yk!w05%`jtOykg63v5JJ&RNLaAf7D<*82*keZzXV zY1Gr6O0ACJBa6EcO*T491NuYa;OiGq=Q`3rGQ@N8f>SqGp1BxHFY`}pJzP6Gje-;= z8;Q2#IFsyhR0Q;QUqJ9{YQaKG3RaI(=ou-Ji}Ifbw_XYfdg;Ct%RPIU$~5mu;`0i% zOssj8y>@2UaRir97G#*;tV3OzI_ZsVxr?{uQWt3Mi_wDvSOE-m_}qrZuqN}XB1bfOS`bx6oIq1VgqrH|#qH#|RwLq<+*Mz^?} z!mPxP+Q8v}_yzIYrIgw6SzsqL?mE^gP078OCe3X8&^vrUwE)c4Hnry>^bNgm>&oDU z0E>!fOOs+*N#Uo7(c=xjJJG6KNJ=nU)Ql6W^0jocXvpxNha`GBYn8K|GPhEspmAZ#z`Aegd6x9{^Hpx z-$tPRwms1co+@D|7hT!+&9<+mnGnB8%($-*%60EZO?z1?CvJLB({!Z@QEBOy&BGX; zLDA;d$sa|SQ-dthI#svIAss3q((eO}d`XlHTi*iC%wLDnbPef{MA_1jZMOZkSxOP_UXzNnsux@vL+(c$ZqS4}2wUDU7|M zHGGP(a*XY?uW`mJ(mD`fx`*vGHUku7iliQbM=ir8`pd`DVWP z9rOwqFE7j+0|6DBbc5FnFLg(M!&M_LZE;ES)VFSdL-zDyw;-}wouX_~L>=_~(y~$X z`;h~k%9`+-TExfK(nufD?(e9pKLEZiS)fv%e+KCw-)NIfvftm^`>ktX+z7;OT)Pgb zPM=;VTZhyN9&}S7i?-N!C_;Ezx`)#%b}}60?>uYLHw53QfJS}q_J8*Z_ zbE3t_4EscVto6Sj*ME(ooIW;k;8iVru{8*$J0F?1UE2sOgjq_<5DKhIDN0~DD&6Esh$iBy5kvPm(Zs)ne=6EF8-mMvT}BJd&KlL=1g2d zYVsq37%csGNuSW|9e@^|DY256MO=E0(=5|0(=5|0(=5|0(=5|0(=5|0(=5| z0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5|0(=5| M0{^cG2yFHJH`%?hqW}N^ literal 0 HcmV?d00001 diff --git a/tests/fixtures/image-300x200.jpeg b/tests/fixtures/image-300x200.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..2762dcad1eb6ad77e35090839c46978151217330 GIT binary patch literal 2294 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 H><|18u8naB literal 0 HcmV?d00001 diff --git a/tests/fixtures/image-800x1200.jpeg b/tests/fixtures/image-800x1200.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..2c3145e84a43384098733a85999246de0a55619c GIT binary patch literal 11294 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 literal 0 HcmV?d00001 diff --git a/tests/fixtures/image-800x600.png b/tests/fixtures/image-800x600.png new file mode 100644 index 0000000000000000000000000000000000000000..a69a35f65cc0b938ecda26be524a09d9f01ba643 GIT binary patch literal 88326 zcmeEOhdD zFEbxlBVjNsbrVTRB^gOcq>`2SO_Mu@FxZJFwgF|b6{sWCWlc}d*;-hr928DclDhTw zL#!QX)48Owp3eda_gUy<;zWu?gp&)#hP2L(F^w_y93!~8L~lWv-ELKSyCvtbeTg%D zsmp9nG44{$Q3Gab4?|}KJAIvw?#`<(%pdAeo$P!aK9l`4g*ynRx6pZAG2nc<;$zLq z&CYRYsXV@y%G)n2x7ONvbFVvAd|?w}8xXM;MIB|mT1!V(q9{71bmjd;&pHntoKbkG ziSyOhCId(3J#-ou-Z#9snJy`Grk#CyTvzPj%qEeusnpmJ$r{vMTBknji zx8qb`9a{)L(I|$)rc8CoM(r)*ow2ZUk-}(`$8llvvmN(4`>A==h9i3)bROOw-H41b zd(hd=k$Vk`PBh_kXTy1BT|4`mhp|>w(KYy^vot6hxbZ3B-I&f-95Jgn1&b0`JF3Q) zI%RM20Z~6TRF}CaFArk}ukm0AtfMd-@Cpn3h-14y1Ppuc?{FB*%LIn_evJb7 zjrj@yKbU*I{l*S_0K*0UI}CmtV&FfnK7fkB{_z@-4c>#Dy&@?i1AbpIurf3>voE0Dr)@kk+th(Ys{Z{7?FFI*xVLlRF_vmN}5|4A_cj5xp^7I36Myn zsMU>|BFg74e7_z1PmIyn#>PT~hsWODp4*)SjH9ZY_Gl9~1QWq}3q zVBX<5$<532b8K*{DCVysN+u45cQnqMm;#xB&k#S!$IB(@vAcB}etw+iy| z{(kFkZ~c9%suR~H+b^**>;9n8Yi^N80@odZM~Xywz_8$dzd%35$yThus>xfMopaw=lsM)QR}$2! z@SiTl+$;y5huz>;@o2H7RY<%de2lm`f(~M2aJll4Fm_Z*3V}w*{R9)`Px^I#fBMh) zpk?$@U~IK~bRIU^LT|>ge!lVd3#1g&=wzH$vwXtp!6vL4 zZ=YSLRiU!s&7@03>4T(82_}I=2K`VM!qAuX!m*S?3`Jp0@LJ!qP|}a%wh)IE?q(>F zNH)IaHK)L@N^G$Vk#$`NgXx8VS@5_$fv-$GjaDGX|o<=Hsd zUlJqSirLO-t6hF!+GXf1tq3(!CY}K846_Zd>1_*`ay5ne=C=5{5*$LHSnyhknshIM z0I#}r*o`R2yuTJNk}C54!0raI84tJ-acVokd$uj4`5-Y3bvbyyspt@i!Fd8(+W zsF5dfklU)41+O?5(B)QKNJETL@!(wHCXIwx`6szPEiArIu;f(sC0F{Q^azdfmXK%> zkAEX|SqV!yk^@!6Ft)kvW^!QR@P9@YEI2<|*n=1~Nt~LsMEH%HXE=#}Sm$3eQI9E? z!l?->Gws6RdngB`QlDh{uHzL^s9SexYCz1d+zKbBTyy5DER+mya#&cxtZZ!!@iy+{ zYw|*E$T4&*POE%bPq$Z5x@7O_gBTv8S!U+{h@V*S*W@+nYC_wCl7~`KtYCayrW8JZ zt?!3?IA!&2p-)})h*U_l5Iz>djO2n42$J^<+5xsuAg1PVLxUnb;hDBH8e+*Xv?0D6 zInq$$!8|N(vd9o$S{71(3P|F!?hffN>gHV2GsOY$Lq8_=w_VmAuDLqd<#w&Rl3~m- z>NYwzZ96msVo{%zk;OW%HrvRNntF9s(f1i4#N>TgxB*73skfci1@zbWK+TIhU3G{J z;8g^m?MGs)bz=A`0cXZhLeeM5G(U2_e9ilWe$)oiBw(1%8u!Q z9P*P2GOygJog$XAmMUwq=-CBwZ>SGfe~il0>|N;^;GVK84l6VXkG~Nb1a)y(@(;{S!EE(p-fyeUu*cpTKEQ8_xux(TkMAY90sqQ4=WyuDxEs6-8^FgHULc zUMp}#Vk#a-MhOBe@iyGbqHXp1Ax(OnP)@QjH5Ptj>k1a%u6$?!gaAHi_q~AMIM|gp z-OXQn5pwxj-++_9*K{7@Bg@Yr0C3h^@P?9M2-8pC47Ag|3b9PyD}MuLgU!oID1(qa z{5x=F$2|{)vW8FUzXRvZV`>5r6F}+V1A;na>6{Mxkj*I||N34xAGCX-0POT*_Q63c z={8$_KaQgi3W>}_poJ0J{e?i(K+_Ie)k;H(S{-@qmHDQrC8bx)sAD=#tB=q%sJUhy zK~Fj5&giNEEzf=W3evznsr89s-!MimcbQT8RllT0F81910JV?T5eW=qw%XMUWAe?M zEG1BQ=us|;lRyo;Min+GSLR4zlQM)aKr;h}uUJ94ROgyBc?qW`&`t+(^9|7YcpG)R zh;4BdRq_Q<65tOU@}-VLSP$W$KY){=sS?W05F_lr0Vh?qX;!C}7S4Czys3i4*Y+v|YDmtDKY=r>XtHQHF7zpcJ(7mS{|1~?nI_>H2gn~oU99f+ z8*mO!y@`XEsb1c1z?oOfNd=*&>S4bFXKv;hloo`U@JfDToF{d<^7wt&4nqux%w$53 zVh1p`*pmBI8#p*QX)3#EKt@H>1ON-oHm66-gkhJl_$s!^A3>~~Q~6KEd5!5_BgEQ0 z%3ToIU!0O)Z1v@i@-t3L>#y=S6lT|d-uzFYFl;lW*>^xH=awRGV zDWUWn;gph%x#gN)iI68DWEA$&15na#)n`x^`3{Gh7?qx$e(qOrtywR2#u`?fwr>c4yrmVsyqMTf7W{@%6r}KXyCx3_fNvM4a#Q6<5J0$HOmEr)r`Cvdc=OETY z3U&T=)k9DNzQcse01-#TTWsUuH~NL{LWYXmaDcE8;9A$D6!sxUx}5Ux+SZRyX@C$8 zUZS%ZUf2Q6<41_SDy&X1u|i-h;wHmy$QhPo+NFUY^MsHpse1bF$f+i21t|gw_$Y-s zAm_B$$*^aYr36qjrQjmHrYCmCTPeiw-dK@Y6Y?FTN{thOz|ypgYv!FqzZhIfowdKJ|nK<)C?{j z49J3?C*%~ufzsxHqHh8Ui#P3R;n$FWx-Qe=FW3}*1hw@ZsEI%LW?bpBR>-7EBn|*U z5Y`u^oa2bAx3)Qq-4dP8an-Y>Q}kN_zoWy*pi7|0RB&@UVUl~BMV#bcoJ z5H)KcNA4v#3x3V+Z$SqBPB&$6vmKz!%L8@Hb7v0ZWUO*bW$!~R9vP7HgKH3H&p%*|c51gJ?Kb;D(*4|Qon;d$PdW}1J2}z}A4*1g6d1?^S(=q!Wb?Z2{l8`YV}rdZ z{vezC1JOaQOfw*ZN?yd9$0nV5^8Z94z_&3OPPhGsjl8A@(kZrbFX2qv^1)CM1gG{- zvT598+w)m|2-4IJQ+{`u_j}AJUkbJ6GoCUIqLgBK&)A(U*}|Jw(MpPKN`PQ*LDdsrbo+AQ3%Lbqpb=yYPU|td%aG~rzH@y8u%U^GkEBb4bc#^xL?6Kc$}I%M2U20guDvv#Q3KqX z{6EF}*9!}Vy+nSs7o&>mFl@-PiVVsmK@kO%MbxprR}xNn+d?8S;sr_+=GYy@fy(A2 zly8n38!E0@zIZRb}*&VCy!`5_d2>e=ohM z4z*EOa2Y~5evqK>!3C*R<~Pw4ki_8Nx9q0aRSy+*RQF*h8I^M)9x#ka5~fZ6;+gxh zw?BC1i?jD2(d9EGm8M<~kilbpJSXyIpzLn!(8wY69TB)PS2nlzA67WO{IO)?WY`59 z>5T|>sIs7X5$XK< zx4hFHCD+{GVu136(z?HhW_;Q6!;oP3^7jyZxC+wPl_|qC^}g8BzBWb&Z-hYm;5iqV z^1Y&Tpmzrq6%|$X)1}{|^S~tqO;IQ#;l&5l9RRVms`pE0CEINOQQ`$oC>9MTwy}3gJ;{| zwWd%32;Qf&dLp2vdYib54I6U31X{;Dw6wLUJ!eWGHzbg278 zt#gq>&Wws31*)H>hpH&liBa98kQR9i0fKG-#T=+_<#g*BX2^MF>Y=ALnoV~L-uQoK zn-rfIL?Bm%i|&VkwBae0pZNKYS}7$z>Vj9EDdqlyeuvLH=wJ+dTDPlGLnvK22!JQQ z6uGxkfR=%rMo=uZzXuft=^cQNQX@eX#k^Qsn9iRVbu%-W@z*~8u`B3!Om=*-$WO8{ zB0;0*(H4|&Q3Jn4>W^lVh9PmD;hO8w2QlUVlhpuzLhsfdehLBNxhaegYgh#Sm~%xH z55gg48t)acRQqj2?pO3@8k6=zlJliKmkfZJF|YjS;D3jn#0G?E+iqq15BojAnQ$2^ za3|psl(~g){|wV}K$t$xvH&TmN56;ZmqC~=8VD^`SqzBzg1p^9kYo;VlZ8a(&y)|j zGV>xBRe~wh$ITO=1OF4G94NYIBM%=;wQ=7#CV@g7&~i>qz4+32=!jaB-s4DYda8ve zT}5*<89BsGqC8Na|A^9=-ULBAV>vje@#r6r)>e(3-E6e&SxUf#(oh&6V}Hfz*NJaK zlSDa8KglgXCwEmm`TH?6KgSQ-}GniSYAaq$UA zOtN73Sr@|bXN6iP>MWz?VM*J^O|6UjRU!eZKK>a_M$^QcN{{`xQFft4}|1VJgU!eZK zK>dG#`hTX-|4pEd!nEDKfNHz-D8K)+CPXP3^&i~QH%MY5z@+atrZH95Z((|+b`E5p zc;7it7U@~?Cy`1@`G{46;|on;Q{Yz!(?Cb>UNjeQi((R*rl0?#dGo9!WR^f$^IO+D z$na^mG1JySmT$1&plPha8mFeFDUWO4Fy(v0GbTQ@=E@BGssLSTx$vw1Xx~iKpM9Is z6K8I1LlOOQC9H+<1ow7K<1FabNHEES+$apqzKKaqkf1+oT8-#{OJ#|QMk%`T0$B4b8?&3kF z0poanRMA1`&z@k?CAh5uo#F$vroGhNHNEN8&Hab9Fhi4j#k8IDB?wp&QicC#+d*d9 z{OovtDb;2xEA#}ih9a%?qyNmVSlj2bfc(G{PRNVZG3D&Nj&~rc+@)*hppFs*l!EkX zZqJd}6tGk7XPEz=^Z&8Q7trch3u~ZTE$v_D7(g*9Wm4p36P#n23;GDdpKY5-KR)LF zYd|0c)lHA?m9DxT3)l-d)A;io$m*)z;Xk`J6NJPd*Mk>#0%VINailFl)3jI2?CRzb zYjwy{2}+8a9{HI+lMk;g$4vdp4<1e3mB>cTYni7dIA<2gMpHikT`Q+^+mML^+~9`scN zV+Rl(g|0QJ{82~$!r2O)%YFDq)TYvQci|h%0imXYf`EQ zF(e@Swi=s~5-{or@;wxr>RAOi}1G*WX=8^fS^Gp!RKWSW49d9lT=) znS90b`Td+w2n}RYj5MYg1-jioy}-FTacv(Tyoe=zXrhRqdhn#EnAqigb?FnVa5_Jt zxF2>NNBZ*_6UgdnIgN*j1LF`<`r>jZVW<|_>cifdxwO;8L9Ix)deB+6N&2M-0MH$%!lma;>E=REzgcZR?Lmz0oWnUN7>_%FVFly)5t~YFwqu)LNtce;H-$qQIU!(Mw#^da zz>BiuA}Ix+DQq$UXqc!X_}1PhnWB*f?IKA3=-E6#1Su9!_fCe#an|x;4p@fn+YI)e zVT=T{GabL!mA7v_@q51>z*y0ST)^PY?8D%`Rf4p^LAZSt{I7P+o_-2td!$r2f3$2KfKvRQEt^t=X)XEt_~1YK z++XagOJP`6UFJge6<7}m0^;mHLk4YVnLpdyBfc&{t_KLS}?em*^40K?|)ur6HtE za3g;7xtI0L--BXr(wF~k*<_n}aSGDNDFNG>NN{&KaZXj07{zV84}~TFR%`qg&8fUr z7lKj=6q4XQc0l!XA)Ki;yHSAXDAbxURlh4Z;B=wBC~UlldmIJL3P~SIHqwK3rVD;~ zrpb_83xvFXHn|5c+5IO5*V(YB`r}yu-&Vm(02=;ncZ>G=llN10aNHOGNPZ9ZG5?GF zDCOSE(4D%#Kf$PLIk{Jg2<#t5-_Oxv0^zglQU6sZfP?y(UcE(@7Zi?Gyv&(esee9bjFcDYUK; zo(gEK+DZAYyz#_9NUH;M_SYdxp8bclCQJiOu6`ye9&u&KP|-i=O?XeCPSV8)@)}%4 z>DTt}PWW{={rb}clf(Wu)*IHy+hu8t%nAc+^p6oYg1 zQnBGH$ek|6;HZj6N$n@E|DWgh_7^n0)(;eYdoY0BC6Ut~3U3|qf5z$|hFi*QwzE6g zB#Wc)fx7i0*IBUEzyVs}`cYK{ z`Pxu$*uCi-?Zd4n0jp55LC>;*fPQ_sO?MEhW;VCnso~wR2PGFj7(q!MZO--$V!@$@ zl#deHSPStuB6#b8kJ}*cn8mQwGU^90y zEG@IE6e^u29U`LQfn)^q+~1O>YV!lVFW^IlUx?4@Fl|9@M``@G&d_%mWjjaR6DNzz z*PY)o)CdjRT0(8Q9tZ;V9)57YDE+u}vq0~$DsThq3O2+dfOq;qZq4}++p_P7&z8mw zoPrv@?>OQcLL08TYU;hw$&n0bJ4y$=US>?olNU9zY-^#`{uRs-zmIfC>YY2}@GlXd z^$9d^+|Dzl*>!KY`)GFk8a>Xa2*m6?%KbS&6RDLM+IFuAs=4x3*=Ya!)vZ_F0nj1p z>%%|ttpLlj;X{j0dlxMRoOfDBPm4kB#pmzm-QG`#;J}Fy zCg@Fu54|KgBEI1ieZ_5Z(tXD{3R2xA(!t4q_3?g?I-+BA5yu`nPC_BRpsCBa-P*SM z+1v^0Q4pkS^N0k3fN1xf(|M&wuj#pt&%Pw46rT|3wer<1%7X?+8w5yTRAV-}!?bH> zWW#b<%A-zXTHRwhDkJ`Idpeob}%^=gR!5xuGj|XDzjN_j6Hc<*Blz zGdfVG-w|$i&{Onn(Ho$m=nr6kd@$pf$X4*IoA+{wt$YTgd`$2$XAN+X!@!q_OU-sOnl)4>SX{Q zcBs`>)(-~oaIM}ZAunB795ml~HtS;Yir)2AzFWm4v}qil1KI-4J`|JCmyQGs+!o(_ zw`f$lxX{zE>pqk#UY0iseJ?Zcf2R(f-CZAz9{kvu_x$Qwl;qu2myuyl-NlZwh3BEO zZacdTTRWp|b5Kuw0>*-g5~{uA*Txg02X0B2qnE!*-u2((Y zIjeL>U6w|5+}yWzzuqp}slVngv7l+b{h$q!Kb3uZID;QoCfy(bFoy^Z$JyAo7u{!; zJ-<3nxAi(s&R^7-eAPP#&2+Xgxg%g)yUkkkt$uYbEWhYFGVH{&+iTqu+E6;W z3oKNuY@8o*d-KUacirjyauIM|e|&s=pzX&%HNOwE)3obf(n`M_0?jMUdFDj1w%e&#?Ib2gS)F*i_4?CWAk7_{%#GM`%I{2$8tN_-KG0MG#x#77*_u) zhOshx)SUC|8_sQi@x_a?Wm==lyAq4f+j`x%*N$f_Zxlh(86c-{%!7Tvi5j5)vscwh zY?bC(Co_(3HyQ1WZMU@@rFWkmmDt^x90hpL*0vl571^xqz&m!qF$*`R_IuTsN98yJ zAL@(?H-EF*I?0m-2Aj8@UH??Oyz^;P*L`)dT6eQ6+PxQ=>sOP4hZ=x$X7jKZ(=PAe zH?}9{ax==bmR`-iDUsN5Z!ppk-#r!W3Q%JAccm=fHJTOejysVjsDo5Hi%?N|af!l? z5`puSsVeoWM0>-%Cq6gYVJ99Q!uG^JVp!(rEGlbix@==BLOUYX@cPQ>rHq@2#T=26 za3<7${vIY9Yln3Rh`Y?#*uW9&nPy*0PRD;KxR1`6SGLqDY_$2nYNqTO$n$|KB`VG? zOyNI|@@sS@ZZtl*`e^-gZ_P`$5n|v}J~y53(xsqUq7TO%B`0$hH@8f>mcG0dK8(cL z_ZvNdFQ*AB9F1~zI(pXs8d93Zzt)e#;5hz=Al5SNt6-F;RyHyo2!ZYIaybc+c<;FmtPQwYzL|Jb`8^OJNFUN4ycae3OHT~G&KZTdV%4-Q9`t*#yiSd3? zxfLa>JJY6za@JdNr(i8EN5@nqe0t?pb$#d%&wr^Koah?74e3$DLr#x&R#Z0*OvopF zZ6N#oD*IglX{~ELEydBX>oXw_SIIThTsY(y_SX=s!zTjEb7FlXs=OMa{3uWfiqYay zI3dNbz6VXu8Vd?aR&drQE(LKr22DJ1kukfx%#>SU^RGQd58%ns9P1S3W<@DY>$-2B zO1A5TqoRaWW;l3!S1!p0u_n_db9^8gS5&5zWBu0z8<`t(u|8i$pK_Ur1TNM6;2n>G zpdB+R?N4NsYC7CKYWZ=@!F7QR+=ClI8v`RoVgFEP=@=(?kWY*xNJ2&kz0@fr+cl$l z_So;W<=RBZl8#B>#clz|c%SJJF7q}iiG6hiXp#pp+K(t8QA7|`A9f{CL5lEb9s#HQ zLNC!vZ>j1JhMN#in(S8*CW<5ox znzGFodVQ@cl-qsnD=gQU=*+a9#R(Mq5SB{e3DpyM zg?QI`IXukxYIbRrpH1xcSH_PWwvCGaf~XkTm|_^8Rej`4Qu$GOdLbqBFgIs`zD*OD zVX3IeKmg@HYJSA$Gx7`VW*J3OE_o8N)WxFPzc3C0N;eQYVpyLwV5eQ#Z*4b7?D}Zg z4@j{2oHL`-jpXs?p&vLu@Dce&E&M5^kh~5Xw$Sa<#l#!`G{PmIk5t{l;v!aguVJ56 z(YA{tb&pzm9__~Q65RYS$RX5(ulPLH#7=yzr?ha~vOjHjVB)`kib6yJ(Lq}Z)PrI| zr12#M59!x4L++it6Ef^%Z6WVBC-CH7FEW1_9LcSiIn{2m6tq9`!0=nVQE~9wIR@B6 z?;nvhox`C(b${3?(buw4rY#i}WY2do4u8&*OeB;+JM*RVxxd>#?GV5}P4`^OT1_GU z69P_~(biYjE@yP(yPvtU`Q$X)vGD3p5=+v2U$Z-_uhqhzlk5mMPG@V>{#W}isR!n# z;2{?+?ivU*{&O#Jmz&Kgw#ZZdzHd#B3)Iz*PI^VqQO@xYk{;;p#YDkTyIeGWJj0I1vpVKYk+( zNONs|unC_usXUu?!&IWkz{|8OVuWyWpj*Vnk(70y)<37ffz7DcWP##xefr&hOLYNX zE~#9^ap6YGQ2--TQt+;5mb$u0!o)}3wcZX7yBf^WcKPLXk{M*F*nuqYnPY(NPlW3nV;>eTE^4)!cw>Og+fb>+QMaCxqn%x z65Sp$Rb710U~|VqP8`dVW%`5L_o;%#uLN9Vx*h)1t1FfGO!Q=fX8kL#e>!jU0-lYc z2N*6A5FYf6Q=T*22ZxAW@|e*+y!*bAHD2oeD}SA3^^OFG*C7$ghmP;hE5NHy1&^3yiQO&!TTRdV@+&Oej^s3VTV&)UHQieXtbWzzr+BG0D8DA# zO#9$JRsYDv7z4zc*DyYp);>gy*lM>y3|#iTPG;t|G-hNW-H^--Ijv&@Qd8nGkqtz3 zqa5A^CBuUghX1BAc5qs9b(*S+UJcI-s{N#b)`hXID^7T=HMwY&3YeJb++(oo=?R-L z(sIe*vs)Kf@3uNT^9A>VwjN$1ZIAU{9E*``bKp|`l*L2(;VBoXd#!0Ha9S=Qd zx3xDYiZ&UX&K~ejmHg~n==gCZCDi1f4y6M?AXPiBxS-%2@$IGNBnl1K+489FhQV1? zwH9OlJeTpqxNS3`w9!v*j!vt3J#QFoxYDXdKlo48T_6j~D}4#SJ*7*oZUsNjvRo;} z&#;pQgvg*jgl^xSsOsLH3bqqcn-!UI5qCGHDb4md{x7a`!V8rHvvSLEh9iR3^UZp~ zbCUEF=SJsWZdwla2qjy_%0{CsvG@-<3&W4wBcNkVFPq?ifM&C< zRPu0#td-f@bY7te}U60&aAJZh6Wsl@PFC@Hyqe%Ry{tc25fz? zLEy{+(KMTKBA<>^=6-X8UUN(VDcZb?GZKXDWYQe=jtB-wTkr}d|6@i z5+}fUrjS(`&8*rLv^hXY>G*lWIoPtUpza&GU>dC+8 zz>VX)`iSjjMG0SuLx2I2e_ zUHhuW`fugUJ`|RTWi?du#P|>vdnR(_Ug=t;uWZBN*$~SLy9nvKn1JG9um-*5vZluM zH;x~xu6{)PlWoXh=n!D6{*jXac&~#{V&;^mnc|GMu2xQX^=wGP;S1Ccd;EV>jO9Yd z+Rcd@d(eA>!D6(Yc5$`W{bCAH{{V?qgV<^qHUCXHtJf_Je9H_Ln=8}Ck+D^W2Ys@< z+6}mNHkQK0KAbD3z3p>4N^Hpe=-{WU`g0+M-wbyn*h7@x+uNCAhgXPkRn^k6EM6eg z<4l#M0at@+-5ceV$i0m%XKp;{SsH7A*p7UQ(d8$PTr4k3V!A9%IVEIGJBE=`| zC7k1B(gQ>T+eSyYW>bSKG1xsu89K^X0(fDA~w@<=@hkdYoq`C;M#*ddVt5^A=57)UEAfBY{b^^*TpPg%YbaS zOl8h#_mp{ey}|v3QSwE4R{MxD>U#(1Z63-;|x-7~sao(@P zDd@e*Ak6G(G|Vg;5{66flKGfBr&Rt<_x4Jc`AZ`spHqU1dlzKslsKHME_#fm7qO?K z(t3cRPaS-Ud+OOIO3LL&x>{%IS6Jh_9Q(c64YTjPyd=6T4G`&!{Fa#nllc3(D}r%u zBOq}wMgnhtYcu{i-njo|y_yg14mrowuxdKzwECVj*WS!QdNO7Z-P;=SOjrhFQf1%i z$Ts#Vj5z71>>x_Pcd`|%^_DVAdcM+lCK$vx?c~gnJq$rxz}45N=;-`d3@T*FgBCxq zMhm1~eZ`)T{h-ye4pC5c{ai`Pqd8$42c4?dM`p4_xkxXviPFu=sNZ<6-X_o6>cI0( zeX+%*=YrQZW|sCCnj<-A@SF^piRFp!vWmcieRyA5AY*A)G@W1DHJ>gaOJ#^Oqv>e} ztWV$rW#GkyBD1LP>}-i1tE9knXMOaEuNRB9n9fKDkFHsi!vKDYj`T?jU6=X$Z|M~_ z1kT2=5E}T_kY+U^yn@PWwfCG z^WGJ&7W2`>J%=@i;vwsocZ~6;ITgwHKAp9s-4fUF7&F=Qj)eP;ivdeT4+mO43?#Sa zhkI}a@eM97zPnH8`z*|or$5$c{nac1zaZ?J*rJ0pDDtg_ogQwkgw^y6g zLrw1Smo5)nSzFK%z0xWTXKK6ycQC3t@GeDR#(iS(X=Egul5jw!;`=RBf} zMceZ=^p@t66QlTe5giSlSHz9#Ba`FP2Ne(|^9rcbdJu((n zeV%Ar-JafVOPAuYlvgtk5wPRkz@r`7 zb}69`;$u~aG){Z`Ans&{jnB!dqXr6?+#}lUIIp-k-Se#^D=WLfD&HrUr``1TAT)xo z)9!jFtpumBX=hGyh9Vxy_JrUg{Y9k+9J{l;tt!;rBbP^V0ZVG}EzengjuWtGaD1fi z?cFCkO3&gjh}~p4U!4B@<|cDAE#-v$;{AJ1aIfcg`Hs6)RVLOMjOK4MEO)JsW5iDn z=WP+@<2y`!YbrXm)H$9v#itp$y%6ILa_rJLhnFZ;z5D1MzTD2lYF1p8^f|SYuV0&} zi(q|_b(!!L^o#8_?OYy8D0T#FJo5r3@eGl!TShm1 z(EKiOm+0|E9+C}*M`x^t9u`^-UZB(R<=Vt}-^6IQA|9XYtERC037!wYwqG_Q)k$M9 zz6RBW-`9dGNOYB1m|?Elx&VX`Ao<>s-ws@75$_&j{wkzo(!HTzVyuHyIDJ+e0TivUd1BD7LnPv4P1vx!n-3E zvh8QOJ1EO?F;3LR9cR%k#I0S)Q~vrzf4WnqKu?#%Mjiw*o!d(`qqh(MS81xMFEmJ{ z&Lk1DqHZus)JusA)%m^N4&>pk_p{&Dcy|Ijt82Q-Mq+S)Sy8!YXc5Gl8xsbAsiI!v zM~b_4qC&Y0*|DascjuX2OI5(1yYIRn+z@`MR&;af^?@KkQ?kgJw*wc;$}(#UuKS#9 zrLx|`^_(X#yCgM34;q>ac2n(5ly-S~9JB3N1_x3M*s4A~KO@w6!=l%9HJ7-WL}H87 z_mp72vd`NQh7uY}N&GS*j57zdjv4#_kaMo^BBrLYeeE051)>6bZ5s~LNbQ8sUU}da zNX~Dx5cO>Pc!wU784qk29bubH^~ccFI%bQ7p%0~>H6jh;=3@M1t|V36Dw@0BBjM@r zs4Lsh`>m(iwR=2MJ5S!5&_^QP?w;C%p3d`q1C`z*TkDI#+MoFwL=7?}OQsj>Uz`2`F&3jLJFUGGgbXdOGG7IO4WZ~xK88FStsPI!~)o&QsjX?*~neldq#v~oL(t$34|0yF)3(+X?mF{<*%i# z&N&8OqVHy5MAyg(&)l>e>-F_iU2*}QNgURt-ZK?g=KM2OJFR4x$=Homt&uo^qC$d zt9CV(^tAU~AWikWwKh6eD?{Yjg}u)W<oL2%!0lf$x=*_y@>OsC;R34(Jq+Y2Li_>=GEo4zAj@U7k!5xno>x zVSTn8&*0oKFm1-TuO_C6~=T}Nmc7h&5DI* zL@OF!>AdMo(=Ha2{4nvj98Zu!;>IA#R?Or=t^C&}z(32LVdD~qfiS3;I+J6DnZ;yo z;Om9w!{jdw7lG^_BT{lU(L~s5w3Q!<1PSll>eqN2LHOjGIC+DZc@b#y%dhhT=C{Qs81DN!+H{UZJZpKQUbe?pOvXCRSiL0ouvY9fzH7Q9 zeMG@aB7+k1UU6=l_$|2p0x{2wd}N%AWAZ0Zqis9~k9J*oMomMLI`na_xX^iZ=ECd} z36_^HlS4?6>!zKw-N$~^g0$LqwE z3v`wQFrF!4a+HiB>`Z6OyIA~U&68}e-FMw~%oFKHk`TJx{GJ9Ufxo?kj~ZrBU{+xc zn~RiicT=rP&8hWeTIZEms5yRfvh~$E`(<|D)#IWDF3! zw>FeV2pb#Qc7|~i7z_$d2B@U3JlD#Z`SUM4jVvr0Md#m>5pbz?A#xN!;Q6XkL7>Do z$?rZvM-d@~1n`JDt7ff5?vrg9LL67ql5FWaPGh8>bOsHo*0J+heur#C@0C-LvsB(V z+-qxj(kzl@Wmx9%>t=0lDi(W0X!$yXFgd~z__>LTFp?#Q z%nZ#KP2;zoIArdz8`opKD9_O9dmMHbexZ}Ae@-ss`sW-!_@Hm*;<*oCcPO*&W~F;d zadX;TULYIu>iM+JmURG#SA^8V7v64@dT!6Vnsuv7HK&*YTJXWg$0sSTqpFH`HuH8H zH+FE4ZLl{bPdJE++j5`)Uf0K#);DSsFh5TB`>y?jX~qE0n$*3x zKT)&`r0%Jh9vt-l6;jjE64mS8sPdwB6V9Ggy7AmLjc`KJ(*4!TK04+GWs7+^&ef}; zSH4{4W$=46FVgwY1MQr22)r9tBG&3Kn!Kqld7rZ?{9AAl;9Jf_uHL@vP4h+!&9eja zHbG`_I5b^W%#Kc1Q@V&pQA_)EEtygNq`p;!&51gJXVabT%slOHpH6> z*JFgat5Vr{ZQv%MlY&$VIa-E2Lh~xUDI@mM2k5&guXQ{r?d3%J5QHisU!;~bv~AVf zWKQ8y4}Qa+jDB#Q^TNA z-OzU$kvM#^RUJ0Y+>W}J6*4+fn>2q1AhVOUSU6>ZEr3 z4!WF0T04$7kW^>goPu%DFLO4?)S-90xbXCq`)Swm>&p`qJK(2?*Axs+#t~?|ak7mo&3K&G z!GhWH0z^uCBctmWtF2(QKfPM7^zq27M~H?dL&A~EbH`%e=u4-|PKw085zfC9oTa|z zur*&jSaelgv}yxn0fM65au74?x>KQ4OH-;_0wAL*lCbI+|6`|Lvbx@bNTJwRC!>eLF7cdh z?n>^U0HUfWjZA#yRHqxKoj$|)O{e*uDmK#TpgSwM&3mmB$hlgcvhx?hbKP;9?6ghw zV$G#wRjV@fNA-b6j(@)KaPVFbQkWrztKe&>j#KjID zT}kO=x^HwsRJQ-w<8M1ndO@$VX!-8o3_hvc`SzgI0Y$5(8(MU_;k39C=RX#^3EdgB zZYHI$Tx72FN{}tpG1KaL^O4sV(2N~~fPGef82>?o)^RLK9zlnlX%ANTgkR7cZm?Xo0nQHQx0^z=!2ECW&5 zv$;3OJ&i6V`G3*TO5J$MypsrOpI7G6?`72+G&3u@TfU%RbW~tj_cVzbUEoh5NY<;#^cXST)SSPFJ-9lGyz(QV7!%323XR z7N4K79}#q+b$N1wNJdB28eLS zC5janrBnw?FDId-)EEqOc?hCwX~{i6VAEN5VKzm0SqNkom-AAMNzV+#Y93~1$wkn} zfH?PZ$A?R+BB`0tYL#rVKBuOR--=2~sl9NRdXZfvnoGB|`{2QY(v%o^fl-%`y!zNT zc6YX$B&qFIK4KQPF}Setd8$CkJ;O!%t~7m7>`WpLH@CU;=`)If66w=%R+zXxi3iPZ zRG&meQbl-7MdFLC8i|gL9u2nlh+%EyY3moyT@3RL+DP8?fmOYJd17~6M%MNFt?^gC zDv;B#MLA8dy#|Txj~P8PFop6yCZ7;+278uN82=@6CIfD;Zn&rXkCG1uxOsa`jSQGrnCd7!4edD9*+udZ0Axq$ZBWZUP|oVvK%*a0gVqJwfforKdt>S%+GePMY6-Qmw3$P z`DyE$9rD8|^kfOMWxJ&xCB=1&=dY(SI9%>2w$BLPChT@zo$9#KHNOMWST7z~a!Gcq z?cAQ$dVd2^TA@DHL>f8vE*ZB@`-R#zlrAYRB;o5nmfkv1*X8w7z_$i{z)0y+0qoX1OfO;@J4C#Az zxS=l6`7>j^9WdMQOCXZnK-UxUu)uidvEPy;Z69afQBs@8)b8S0ZpS1(G^N`^aV<%U zx6M8cHN-7_DBO-^oS19-qz;@jJDxGM)jc!gc3fjml$W55NhnwNL~PFTDWS8>2U_&b z(uRZ>PivJ}^n1RI4mn6f^bFL{v{DP@rj7ag>nr6d-k$^Ph7Dh<(5e#kB|5LA5}ChZ zJ9v**f#CKBOjd`2TPx{{R)SrQs{Ft`W(Ca#) z`0nlVyyu+X7~dJ^{lkA8GH|VXtvRoG#auZ^SOjNITqw~6!^Y6#C;n(OI->uUqdN9Zx%9?+*gHv5QRipZzraitgC8d>-&9^`kjJy?VF@@Ay2i^ z7z^?j6K(1AJ4#CWbSC$B*zS#(a^k>mZ*?B_tZ2jMs}{O^g(YQ;7+L zmib+{pRSs}{(-xbbUzYL*(xlLHAszr$`f7#Ln>opKq#jS%d7UYSsQh~{r=V}pW3ds z9Z}@GN1C5i$h`bIbKi}O3)xPo`GK%(r0~n*J6W(!Zx+8aT$8#4%2` z4aTo=pe#y3^YxJsy(Nx5GNf|^2M5#DjFvEeoqW`O*|5KS9kxUve~q5X=lIR%dbfUy zxX!Ex6ZvuCEn|cKukol*t28{eExiire9!)>cjmwORuR0}$&g%)RJJDwJLx$iYYURt zo0kBdT}KP6qNxTJz(8pNAP{e{0G3{wy{X~RWneY*T(EPRUw-Kc6 z2H1yKZSp^g0-wwOwlj#iqHq~)K>3);a<9*$co)&Hb_cJpJ0tp=_uGo!;x&J4UaZu= z0=`6D{Cu_t$mtd&4|}U|#+^;Fj3w*r7ObCm{=tvR!?ck+e*Z8%(a867VwS9&^`W)Y zC`$}W-KbYzl1BdPHui=a79~Jx_2PW~7E~YSK z{m&5+x1~Ak9>m26rlH%2%TJfQyu9XA5eGp!z1M6!c5vHAEzE$?uwV_E&yxu<-}e zAQ0eq`!k6~)pyleX-{(Z@whR!Vx}YVxwdWqYxBK@?YCi#!*LCA;w1g9pv*}f-cB)} znI-qhzhK-E{$86}zI<{cscG_6BDq1%3GOO|!wWmIZ%;=>F}hBBW;VZi&cATu%fS{D zh1-@-=>x_Po#e|((!V`HagpYgt2wz(Xg%Hr_8jgclCfCLVy$F`3?H@Z!f$iK^8;tY zlDMQB z$}_Lbgs4#iB$byaU!wGiJl_+JyP6%E1MvK4!o4i7=qEjUYF8ealAg7!Zc#QzCHt8< ztSy>;ZVZ&>d2g;ihrLw1l9G~Sij~;#K5Io0C<{LLWO=@KcYB>R2>X-%da<|h2SwuA z_v<6zA_DG0&~O;oa1P6U)HWQ_{1&p1+_HQEe$)^N6r;DB*k<+KV-LsuPA9a{tSkBx zUPKvKlR6Viv$tJjb@m0&W4cwFu4g5*oQx{G1!W|JJ1pvnihnMhMTPglB`t70~ z61R@Zlz5*q^}x52aFI&QSm_WdB5}}dlKiQ4BwYeo}XR}kEYFn55?-zW) z0IVC4&m7i6KX3e-N7WC=^BC9^7Uxv?pYE=g?ulk2^RAu?5&yc(EJX5lt`N+p;WLfC z$NEP*@6bRR!HC7WpGD}zh~;~%!^li<_0qQ@BO3k_TV+-FrunXK|$6ULo;59qt0EMYj5FTjzjH=^w5b?-^Ziy%RWM00ZM*n@I(Z}8|9 zYsP4O_bs(;)I(t;`2vnj)fub*3M|a%32cVeaAf(VuHPDk{9%m}6ZrMH!*RCIt@2ri zBJtyzpVdPm3f@{4w_{aCe+yNTN?@)3{hd`HG8Xjq!3)SO1oLl<|-uq{PE+*`1?m@ zvlVh>gn zA@4ZQ$VNj^85}Qituk`icNnB`wGu$D39U_Tu~ZO>X8dKx+2EOj*r&GVbhrK_J$1co(6STlBq$3)Ap2(!=^KtOy?}Sjg z=>0@f4Z@~hj!iN!73*Xyeu&3f-<$@w8i{$NYwF#-&}$!yxy;c`Kw_>1wj_)&|pTz)*uf zGaBCjEbkNM5;mxNj}6UP9xphpmx^Ld+6}=R~C7iJTZ4`11Dg^0t#u#2v=V<0n z9ykt^%`^v}3-@{F(qN9<4fX^O)A9DJ)N7N1!F>w0pBM7p*K>IpZ$I3inw;v<;D6jW z!*l^ledN4$@v~M0nrmVUh~rPc#CC`(ugBD3m?y&1|vUU75(eSKB*-? z@(=xUnE0?*w2TFwsRFb++73scUY^j!uiz1-Z!hK;o9v>@7c9ucZh*(;p$n-E`bn^) zvIqIAxVfWM*g!{znB6JlCTKp&8TQ;gmqm1#nJx>;x}!0|J*<9TVW^F z@;A_hXCTI7I)LhdO|RJ>Pya-JvLeF~NZu*LMjl@YPsnZ)qw68=*QeW41A)j7{*21I zMhNg{L+)1qvH7wBGJ^KIFZn9kj5LDEsaDYtg~|L-GRZ+rPIkOEq`z2MUXR`Ng1@wX0>lG>74$uFqDK{(nKTua?+I!>QLQ;SEpuo9GwEcb zqyw29vVrxHM(vZ#fxZC@69m%3Ul$SLZiNtEcpfw&yhwf^Njp4*QWN=@XF$4JaKD9M zCWiUAnG;O>$KXVW7Ez*evhT?V7#cD@f0GiR0-a_? z5q+y3EX&&^tnl8gow_p0@cVK8^=A(*q#Y7LZNcV;PQVs~{&CCjhUYh>7VMzTz;W)~ z>JL{7SHPItF8ZD?l=P^7d4BxLp(vU#UU$q*9zUgo>l(lbmSFd+x(|7~@c=7B;UpUC zh6g2R+_Wm_@Pj%S{g^^#Agjll6Pea~rl9{nApF0=;X;y-#md$jV5|rDjiWM1o!UY{ z^$e$fk6~--MXW)B9>p|w$Dfa(T&k_Qj}qzA(no4egW{<85J%}pYA%C%lvupfmNBgM zXbp{GF`F)mndqg)(8N`X-h?+E-IYqI?|xQcvyluPUwU;8e1dC0_h&X_-y#f_w?rnt z+{li3NZ-p%yT3^~u%w$>@lCFnrw_zI?1A++*GW!sP9+~HBnnQDa0kj^QIF*-$N0s< z-zTikjut);IY-$r*|ajzf8HoVd)~KOma^%ExlNqFy*tt80XoGNy4b)sptJ~7qDB{K zj;iACwIctefkowo5MO7SsLCr~%PlAeS*6}o$RM|`UMS{k$cSxUcC|_D6ormBr%Ghb z(*>+E3MoTm$%(0kQu)nIbPObqW|c<_T;63v`4t7JZL2b}4%<87)p1r?Oc9kxr9UVD zIFy2x5|8f(8O<3jH4R8o^oz@of z#?L9U_OD_1)_8$`cFXdT*bTOFk{5a<--z>$aK6zwA3RghuSRYYI{=Ov07Hz1$Ifgm ztbi z_uQ^6E1raIVvKz#HN@guJYTa4qfxUvdt(0VznS4T8N!ers@?UgaU_t$HK*;>%2kXiF=crKb+cPpS>UyX&c9b^X1m?&EIrlrs6-GI`LqP5=o%#3KDwemEBPr zpF4uYQG*3-YJSPMILOCj8ll|X94lA5?=OxDhAgaOf9T{*uHVyU(UTGdsrBCfk@uoXfwN z^SiFU`_|d5m6!j)ZRl1pu!-pJsyQs108IgH%L81?zq0Tt0}(~D-GV^1(`tW^O{t8l z9?z*mEwFpn=+;=NZeaoYYD=TXq1l#`F6KiV9J16<`)n@L6&3QvWB6stQiHTR$D}ZD z0ekP*h5q;>Y;dU1LY{D8R0hbY>RY#4x0Y>OV36uAeaXhw|IYWKU$;*frZETjNkdd$?bX{zKtyFqfeDQ^tJD{GR`IC*V^%0+DU3D2wCT!kg31O^83n6aEfXWPKB#i+H5)Rs~VQBIeH#ii&4VUwuTb2+cQ zE~O`*iC*g#R?=RMw;-2N=wX`{zWfvScA`kLkkeXe9(22fUnef)xftYOvp>?NUj21N z03%N}8k+Q1B&?@#=MFvWhju#4zGdu#+KV8_8QTCiPDS#4FqHZKv)vU$Be+qu9S;gJ zQ|kQVK#G&s{~Bf0mh;U#pRX=Py6OkMT-+c<3HvqFgVD#PHbTE+Gp>7Q0+??6$!7^G}-d8P0M-L`1|3 zeX2GmEhlCB^eW-!Z=ZrjzKX&XinepHq&uIf04lO0qXx;ENF1!Y%>141FdOU0|e@GO@0yLn+`# z#OK$G>#igB4FWshqA&3uRCd)ZDISO5KX8Qg^hhO_;u`ZmZ_MXao=JcF@)IadPDmG} zH@|{$fuqn}ejm#S#bKv?EBhBPx0RWde*E)7+23S%(QBLa%b}#ceam6!xybt(o*#>? z-VEtf{cTTL2=hmJqwiHCYeRpv#Z=l=w}6BJGghX_1qkNJEAY^+IH*yX*G#`Y)Z-FDC zqw6$8_r{LYn8XopQ<8W5_5?6B2Vs94VPKZmEer<60x@3CE~FMN~;s%gcCw?|}1 zltVfvObQhNA#&c>f!M^Um{!#kd=4ETzGArg$bEO#0?c&e^9gGT*T6|Z9aR6BeFSFW zPs1P9=vnOO@I}l_me_dQ2XRn!99wFh{9}UyToqHO_MizG|!Is@&7obr8 zD})Uyg#qqSU;3M8zdR+}8Vlw)_GUiRr|l^g=Y$c|`gQL(ft858xlr!Z97$0C0M8MI3o?q zQ{Pw)1LM@RC(vHjXTM{w=-3Ux&%J$gu^hqv6X*gOg6%$+PSswgTTJYmQtn7a!6pYc zfKG{U;~_HiH}F+RWaHM2eEEH1Jz{E{sm*HS=`pZBUN?G~LRiWksLn*@!a z@_h-!4&+dal)`;|U|t=OV1kc^MWch~3Ft1HcIvD~*+viy2`139B@!zBl`JJWI!oN* zb6G|D#F$<95f-Hr_B!LB+}f z`T=vItYmkO*>{LYYUpTHeyppw%JDhrd(Wfn>3v=N+TX1;8)HPRS0Rd+Dl#D$zQBBo zpM!&>DW-GKyBQ{cx&NRi8k0xE)ci~6yV)A1iF3?z-^lvVoP~|7k^HQ=j!o&CMXMkG z(W*uW;iD>bpdJX~`uX;vdx5mSG1tt}2?2HHuD%C)l(P&>dvJh&7%(VhO8?B?2yPFS zrv>N}YfzhszT%(@qB@QuU_H}C6{M^@e#m~WNASkY*pYQQH-1gF%}^wYib3DOT3m8e zY1-zbaD%7q_Dmm{TZinkoA@Rm?9d`S$zE`9m^erj4`em25Hl=*%*fo^)U7GB6jT*R z!6|vhBuCTQIo84T?{nQ-g@kJHfu(mYkFE1TG}5T=r2!+e&|GI54$;i9(0WK6F;w~Z z#8NaBef(xG-`9xWc`fo1Xg`weWQ|AS3+#(Fpn$m1^1hokabVB;D^Rr)0O~KKPf+NF z+ZGW8d4r9s;UAK0Zn+qyw7)u}UZ>p(_k|TuAu6UkYAt(mCVs$x#%sHh;sFW8cYf{j zyWYrvq_TTiW1P6l-xnDj;~dS3>sW0MROI~tph=*qwwZz zV5V9}t06F#DZSMMhd5}yALX~0c|OCvLv$01H`b2ws1ejUR=wWd6HZ5e{v)OMuu? z^9KKyzUvk?gx(3${E+|61I|75tp^IZXMbp2rw{m{Q<_W&b%ltw;cMm5y{)0SqP3A@ zzvoTT)`jfptdO>8-rO_EE&1152+5$ODWKKZ(QlQ(;D z3Xld4EcGR^M$Ye5J`FAgt8@^S{t;knwFFJVW%z!!zf?Zz`r6HOG(rsr-n;lxsAqXZ z3(ksC_th8mxRn!EcWn&&SK=w&O^bzCJS>4&{r|W^83Z@3 zifxMgEyh+10IRUvccdeWupSD-NmM0+$P!ds#-*2llxfpP7%dles73DnB4fplB4&RU%Sh-M^h^H5@zT988-@ja0S@}BSyb33!nDxhD6NiK$01eAH zgN!sGU6rLTc($>5HvT64GMC_6wGbm)fWt2A^-XVMn~<9UdwUAeqkp6YRwryXg8~rQ z8Rkif0cb28<=|1UI$D-iMS5#Vnf8TmH{8TuAR%(K@$483xy4)yxH6ZVo~K~WEk5XW zUxy2ZcH01oWK7TF8!(!GCpPvO`3dEIZoc`Ju*>-=eJdBr)t<5Msb*B(RTDN#kjdyS zh~+U;{GmlB7S(Xz&B9kSpN&HJTou>A{ta#7Go6B3!q3Fp()vZUxt-u^zqzGS?p=($ z8IynzT$TVU*;z}WD3LECp?O==pzI_8*F>TtY02NH5}6dWTA=IQO+hEV)`ymxAIQ>r z#ICeo4p%Ezye=1NfImgqfMVJ9lTGFScpK>g(nf*vTWu^^-}q6ScPPd(@P2Aq|2hDS z`-g|$l=pP`zxwg@<2u1*CVm9r+Pi)K`{VAbY%cc#v#KX?XST$pm7#jXJ1DvF$_NDZ zKvIEv;4(H#O&^U^Q3lw2oh`1C;qtzP=J!{fSCP`yMo}IcsqCC1LHQ~ml9DDeXhZol zS&e;kyG%>5cT=3WJf@~E6GFvYDKvhl!Y4)eA?k~AaEb5;P;5GXf8R4lPwgCG7 z=e037Y>v_eFGLZV7foujnj^R>IO3cnoX%#-@z@h1KRr zoeqKYA3ZBq!iDvc#<$$&NvRyWfqy$kX_t--dytjkOJdO)SxcLBc%tun22&57PMOt# z&bHAod))H$hj2?KY`HFtYGVk|TQ0sY6QOHn#60Q0-~Z!-yh?*d6H^favGHsl>yRMm zGU81|JA(*Q+Y5Mk>Dh~;q*@;OkBVT0gIGY)sc;8)-_cYh;^{Fk-LMOs1{$`z;tj|h z`VCt|a+Yq(VJWsw+`iDob+w$vFQU2qrV(r*OKz(Vf6aarXeY`z6T7%-7cLzUC<~dQ zJ$RsCOTuh)$dXIr5$bcfn#c_;s=-#wn@$SG7NE(3tg}X0m&LYCamUb)`CZ-@ZtGMV z|1H^gg&kz%heA>B?E9@CM1-CpHmnOZVK)T78)F% zsdXCMr}NZ@SpAUfNlD&m58U*QxB*yQ{z3}(e)Vr`z`(@)gpJD@i z5|}oRNp70Hsqik~XIfNlE(5s;b7Xy9GPpP#Y#1b$RcOv1B|ehlHzj=Ag)6Ed*h=Iz zo4@xHIxET&1cto^P6qLYi;+ls=-MC8mmlJ%6okTlrGHc>lnP(V@n}!Q?6|NhvI@b* zn?{oR43aDrG@2oWZA8v0wLy2nhH014Vl;{_}~I zorRD7^WB%dhn0%_P=^N+5&<~|mFE4V-xQfxRqlR`CM3YNV2`NSM)&;IPBHZ$+@m}C-zNvNJ>Qz$p9HQgn=MSNt)=#FZ55>?C4IP) zBG@vzxo&ysbJm@bgZ$kX;b!wWLD9Bf$xL zTfNzKv5a*N2w&-T^RVoRTiew?e{z~vq6Oy--4|BYd z_jI}YUvyD<6$`zoU0YvYxIA80)VsY{iD?GA&qR(5K#(=U`*?u&<@t6mj<%6!E?C9t zzZ4^>c}L=0>ir#%N=x*+KJbJI7{P6w*px;M#qRB?guTWMTRbYSmFU`>feg?Dbh_$p zB8ROOq%rw?7`8C`3&TWZJ8M>!=FMnjH zo3(hecn!=Jc4vm-=PXU`eax0a>8^mWh0T_-?=N|*MD2mi1it)Q6Szl-?KeH8<>e_{ z$1(ml=9^3HuSFOc#1Rlt>hO}1(vxj@wy?^yiW>_Hnd)n5;-CM*-=9A(uTHR*Sr^fr zTi)NU4HuR6X7v^>RjRkWOY)oXWNQ~5dXZz7zEX{ggsx%y3y^27fZrS0pWLcvhRaHH5ZPQ8B?|kCBNfPD+eDmk!{ih zkF^c(7n(OjByh36-)nO7ky!4m@2lUoPA&OHI03lW1Z+Q}%Nn^E+2M$>U^5CQW`O>$ zd513Sy~^Gv)qI+p>lfR`_tt0U@d&b;i79B*0b-~q^jY}SQE{pWuXasQWRHs8qi{-W z(d&1TA)!A^=>TezLH39Pd`(DQUP_I28s_=Db4>H;q&_cd?Sln`+q5y_*AXCcW8`xv z6`}sc4+n-%y@jqCCaYyyqnw~(zuyl2?H<^bxmW7csW&8a961M)u$_84B8-TxUe>g- znnBbkqG+zU58MqBXzO=>MbhFTJDeeS)=siWo+iP zzOWcXl@LYy;4MY}(%l(v^@u9j*OFgGT9p*L+4uV=u`s@P@Sp;RcYxH0JH9W&SLy%+ zq!pG}62vSV?}ZWw>3+*lHQOuW{J9sl86~!d=cjr-RPC(^t?63%b3Fd9+joQ#m(nds z)p&;vXC5GeNKz*I`%^FBt0Vo^NzHPpt!a%1lfdymK$agZDC}yX%GJLLIK?XX9WF4_ zqlKAF@#PAt>v851S2Kd;L8vWW*g%yI8|VshKI4`3PaEh@OHyr`084 z1}y#Hw_G1*+`khiOIra2l}C`6K>|GLMa&$W!VB_&6V#|$^;m?Dy3q^gN`>FaAOvn< z!lzu-gRU(|`j$MQ{S3%S&jT^5o~gs|Ms|kV#rI_VizaCzJ7q#PQo8S%E=X0>{ZuHx z(GymLsKzhuh7cQ7z%SDS#90SMuT}?CjRg9WxHES?QAgg83{o|K(X_)Cl#4G`Ey{h3 zK$Hp;AuaXB@qIghtR3=+U4G!QdFhr7EUtzT#$9=rw_mTQu*jfpAf^dzT5+!@K5?pK zTzN4Yw*Qn!R52A95d}{cGZyLjW+jA`_5;3}ySn5wILj|Y7eE_W0Ikt*lSix75%eSn zT;Y>g_5AM4h*foM|EsZ#*GPiFJTQSa3%$6OY$TH1IM)d;Z({-y{ap9Hl&tJ}Wr5hq#7Hurf)87?o`PK4sDp}z|v0`ZCogBC>QfGDtg!k(j( zmvnPl?oWwoD={m`;>xH3bfCJ-dO@SPK z2+fUj@5B)TnK4Vs%bURzICKlHLi63?aIG8!2j_{<2A9kaYK6z`COAjOdK7a`8e*T6 z9Lrqq%iC6IOFh+HPVUv6x`mJ?3G`yr{Vs&=x@v|t$MP3IP($9fN??@A^UtTz^~Ycz zWX@Q@@2c>&V;dJkS%e=idUEzKCKeqTwa!_j)N1si&s41q25z~xdYs-@-HA@oZV;m2 ziJ8o!>M>Q|)To(oVtCb4y^p1qmR+#hH5CL^PvI9Zh^j`fTi04Q=x5_#Dmqaf^$00+ zIDPJO-0Y~Oc$}%B?kR(*>q@_2$+kZhuPd6N>2Iv;SYBG1%;jwGT9M=0=W~^GfYl=I zz`ZyrTOio2B}#^Q zfcqeQeR3}ofM9m7$o~`xojR5dFA9ObR%hwQc7gHtt%ex)#dY1Ok3MO3uo~b0G|Zd- zd&6YZHqjY1+U(<394=wFJE4X%Z!d?Mh&sBO1wBoektup=d~?S09jS!fQ? z%Tb?qk{EfqTh#BmolBW?mc^sz+K=hyAr(YzWX6|3##-C~(LH~1eZKGBemP*z9OnA_ zTZom$Ytp!!?KYKcCdqJ3OJC7hvLpV|EiLYXH#55a6Pnumx%`x;SzK9O4nMLY)iL?8 zlm`P5kh-47$_D1n=Xhl)Q=T6VUJGqMJ#cMe9XsorCGs~e*StBLvzgh3xHj1y_nyE8 zoiBGi6KGtIDKdQV#4?2t72nQSarN7X^(L3Mp6TWLLxofzIVTpX_jP1aUukx))Q&+2 zjL#PXh?qV#0ZG{3S~Z@f7Zg2gs@Mh}Ug zQ>#Ra%|NhD3MV){fc?5z*!%1iVvL{sMxKE))aPu*@+|?SyUqQ-fTO_7@hVwvK*im^5mWa!^aw^ zsWbEI%X;g1{k7Ro1X40GhHC9Ml)U)%035&+et3#6h7kCbc$x(91uri#Dv@m9mzF#l z@yOVwKCOyS1SCy-mGvP2K@9brPu`4Ey3hYU1B--KH=_Nx4^r&g95Z~5KI&Fbmo8LS zSF2Vq?6w-!Z$cEJyeb)EMDH5Z<;zvs5;pO}MJNjfQCyjI;^F&Q_7UYG+=%(Z(zPbv zpA&`DU=#IU4yn4$7TdAXQEKrfZ@ruHjoZs$iFop8W6{O}*}=9IC`?tdAf&MX-50>^nB4lMV;3P_^V5p=$& z_t}3tGaH^_P@4w?2hVldW+OM@@ADpX^4~u19a>@#q={r}Zl}!Su?4p|+Yze|Epejm zll!iQ8T#4cN@)TXXR8d0T2V^l>eggsOXX(#p0|KAT~Op*7%$J$KH^JIW@YY4LBjTo zNH3Zgt0l_aD%83%&FuJ!^nobX>OquL%J)+WO>Do5?XQ=VTtmpYUPxP9n&Gb&6m%Zv zqG+z~RrnG=H_y6w@Wi8Icd@lOU*ULC-@Xw(-{dz*J>L{j$tIF+)X581-+GxV2Gc+J z75pTif^j8Q;Ozcx|9&2L@ohRcC1kvkxjx6iZwVR_!Pv{{0cl^Fs}~BGB?HSeyn{5Z zy!G!{!6RNLrhDvHumab>*oDJtkwmYY%Az^8tDM)B&Ot*t->sqYIS3rvAc}Z2+GsM; z=9k)aRMnHod=YZ2&Ule^Ka~rv3=^783X2k8?y6l{Z_FE)WR%DUNg&X zJLIBbs`#Av9Nyr0XD}y033!JX6+PC1f8}JYc_R3Vw-lgGWv=zG3D4?5_~a-}(4nuK za0iTPO_YLeZ@Af~t^qtFoA_+A-jN18IC#0NSVFIJi!+41d7y+dS)aVrG{tkluG$z; zx2xn@#;(uyBHa?l$gRMHKoj=Eu-@u{;vRCfxm}rj>?=#n@#OL) z$}YVUsyYlgZYzGX+>G-8&D)s^02by!Amq(xOI9JWaw^|%r3?|<(K<(2%HmI_S8Qgg zd%*jYe_6$dP94zEfK{`O0LkqTn1{ZXlZ?j*p!KJf2qK|zjVm?5Mnvf+s<`>QE^6~d zP@UT|Lk&w8?fnUzArs!!Ve=_)O}c|s)F%YU^ky(hp>iXHS3c)nYe{&xZAK!4J37t^Ia#dzb!ggs$oX!LFe|ZTXNRE=4vr=81-%ISY@dE;R62@!Z>WW8 zw7aWa2oa16c?*x~^y_*;Ts;vsqi!DQFoB!(5+gAT2kJ;7tT~bK#T47mLmBkatef0b zA$+NOk@)hsMI=~9t6nBoas8r~jhA`dwDskArd8N2(LmXbKA4V_&eg#SD%Mxk)z*(2 zaJoH+zQAAdJ6^ORMe3?<-5@rHy&vBo)`hzbQ z6;zYwtZbC)V&JHlS;a6*B4Gq@jGQvUvM7y!_zV#yw{`L<-R}zG4k91qzD;+j->>9) z{2~j6t$N!5hj5GdgD?EZ`g!{qV_N$jB!>x&iB>Xw7iLiw4aOLcSjGWmgAS&77I=_t6wF+P5J zz~+hMZ!QVABnH4NJc29{LeBr{v5RrhwR*%6@B}tI&CUfQAo0MhCAsY=gV2 zsdlKa)j_`KEtAKe8%AR+5ppE-$e51rv>Uac+5v`Ua&j`uIQDSRyLC{HIC<&6oj}pp zO)lRLax5KW2)OodW@uinP~DT{c46`_!3SV>5TcEh{8M%f$ei^>cM^9WKnA3ypVTr+ zwbv9Y`rjRAutJH_%*V@5i_6={7M|+`z(q7k;pEB?)%HPC;Uh_LjDemvr{2MzsBf?2 znA|9eFYCCh&p?ouWwIfBzx0}5Az$Z<(Vbi2l9)dMOTVVJ;VMx2_`%5UhEweQI5%#> z*X5HLKeTu%z~Ix6`dVAU{gTz6FzEmlJopLgRR(WvB9{{CoHC*&2<&{>lY)7y`=+~^ zUj4Vgjzb4gc(o)ytu#E{O%3l2Nrc_n7v^`qz6&{*0P5@k!3tL((V_^^7c!N2uFB%& zA;G`MDqo%rVL?uYX0L%eQ~!%YG)&rivrq~k5%BjE$EjUje|mwBHVuiIEG>7$TuU5J zI_S?OWMf}M{&$XsQZSpK`<@Hfe|C_mZ0>hs+MqnrnsJ58BF`>P7U6cfLh&DN?Ao#5 zr}>Eh^t<)=H%2tB72=+w>s1a>17hA4ZqVz7aRXmrvfNgVB;vcy_X_SGmlSihDb-ud z{x8bO@BdCYJ=E%O3bM~_Rl6!SWlOj$x*nN11k2~fd;z|t{{x+pGUk)11QY3&Ycw|O zqf`b+?BqB4NLT6%rj6MsU8%ZI{jp?ze(_tB0037`C=3Y2^Jzk!PQR$isBonowtNy! z%^b1fTZqsj9MH_;hlMAAK#@SMKs95wP-37(Q-jg^bj8CTr{+2JJwtEU*Ma;_*2JU$G?|D@0p6 zG@L}pB7?b@5jBfYCnCa?cM6L9N{Ya~a7AR%GsDu*)%U-hHAzYWR^PnOJ{WIMqk(v| zXp)r-*UN`t<<`k;Ay12+nZ^v%etK`6O3VMJTvw$XSNV@Q(p6cHt+hr`LH1xVXa38*8k9EWdAj7hQ?sRKV!@uhmW%t7e;vr`okXR z6Q&RPbgu#F?o>bTq%hdZyZ<)XUe{RUgzgPt#42&4QN~@(&w8Q$!W5-{LDiADP`|Q2 z6v58%(Kf~qJYUSn(I6FX_+Qo8@8?@a`k9O)a~z z^l9*{I-RhB1aWlx{a{~$misOsL{geP4wpN~r?&~t6L23w{8*!sp46IoiWc3046aup zg9Q8lPw#DDHp23_)2AoM3Uu(vS&|x%epcg#rP7!sI4M@#e-U*l>pMvVL_tK@M+R@j zZS(w3_pjH7GGe3&*UCq(({D*MO=mopwh7!@v9R0nEKF!lBId!Y@O!+`T9r#QYORno z*DN{QB0gBw;_kK11JR@Cn+>i?oFI-zImehM_6ufrbWtc1ABI&~fkC-xOo%_2jb<~q zB#7&U2hd+1D4P1+fH`Pp({DV>0I&;tV5Qv7rH0nC&(f!zUrn#m$B%I_AH%0!Ow3o$ z#FPxdOQwthC_m3H{|7=YK?Q*u!+ce0qTHz(U~zr!6%E(8M}(-Qwoj}4MFr$UFMc7P z1AgJe>FS%S*Fd@9#jDWA<6n#VB3S#QDFx@VV?<_;3&Aq6zoXB&LA$I}t@4Y?KIoJ~@URKm-d`+`1a$H{yGnu|MGD@ReTRxy9BBZW(Hawu?`t7o2 zuQm-(T6|83q;@sDWeRna0-hYv9x*1LZ&yFmKj`wegVR?YiBJSXNCld%v~X1N#BIUa z=GaFJ5gt>*g@V-$kBE0bVBYtgvd<5P+;ih6PYM z0O@Cv_I`Cw_vlHNT@}tEG3k zfr~OPW@X&2?rHz*7tLOSrv>_&zSzzB(Z1^Cy&mq54Lz8{u#{)JvB&R_OdH`19vs+V znDE8#Gz>7={nlsxQlJ)&Qx$0z<}nW|a=!Vu&WC3RoZGpfXF z0HnILUoY$jDdmP)aIZ&5ZORnsN4TvChpig0Ya9F4dIK@|q?ng9R(>z>A&0(6_}u+4g{Y%3y_y^Nf)QmcJ{>kXm;m$SHpuV0GlI z7-Xj^vF7=)Uir9ib8#jsa#V<#3_D-dk%*2qH%;oA?*W`~2^BMYT( zL$v{&jVW^}SU%#7Dx97?$#sqor++*}U`v!sMQ{TtBNiTbt6KNZI7Awuj(tOMe0;nI z7VsjA#wZ>9OTeIHz?LCzmVT&0k5_@S%SnF0MD>aPjblE)2JqEA+XGVNn@UUxBL>SS-L%C6%KajEN+@I zM7)q^+KU%>Ev^`m#pNhZEc5rxyT}kTLjh>>G$;BW%1|KZzkew4Rkohzc2qG!QX^gRMVMv zQ?eBG8G#ZJpA6d$p$dvqO~&T|cMX#YxyG7gTHq>i^>sZQae$gn71&L?an&V(S@Nd` z7mh*{>w>sZ@G6K%P6#3nhX}654R3TbJ#3R7G#M*L=tt}QLnL53!N{{tq8OD5*_Ztp1HdX|e~Zl*5!-vbfRed*Ng z5OeaWl`&rA0=}5ZI~2fPI~Gd9iLRH>o;ffem>|OPy8#^Vbnkhr{qTZdhVl+T)0m)5 zBFmkrS4l$2nmg7&FK`FSiP;yg`R1iGiiARPX&UUw%#6k8dmW*F0o|cu%ODMhT_>)x z1e~k$hHx5-wcjggNR2aRR=DpQ<$H2VM69M--(t?b_ggdC=1m!3T-ckP)hiEU)L?h{ zd_5SaJ6OoGgDbP4_x$$Di-$V#aP55aE-nZZ0qR&nSrm9N?;g>E(?)x12^FY_C@iR4 zko-^&{dhmuW&IlNA$}vz)yMfMz7eD4`6Aqht)nKot80{N>S4Fe?`AH&vgJ`v_XV1%*$*RTDnSaesnB88dYHD_vPG@sia76vmAPo zj}vCflE6fccKSYFfO7oOL^ZUrOT&2jv}Ymf;Wa@zk#yR61&$v)+_JgeXe}kKo2&a2 zU9I-{m|cw2un!((i-nCIO7xB8j%DWEZvB!Qw7EMA)JoyKvgSRYq%RGbayQ9fQ-Q5= zH#aSUK&V=>9mU}j7KZyv6VJ3(>vi+6p51D$`cqg@BcaDL{(tSg2{cvv8$W!Uh$ti} z%1~4kny3(tlnj~YS)&ljnAy=S6(VU;hKzAck+BS=q`@3VhNxsZh6~|wgcUrot?FJGWiQ-D*a9P`RDq7-b7!L&-?Ov-I{F}^T)1l@Z^GkSj{wBz7PSBYmC)35k(t-A2aV)l=eh&% zUHa3#viS$c1&g+FyY#t#skD91QFwolhhfL5j>2?)u73BaEpt0Ef^WpUk$4@PPgu`zqok{!CDUR3$K4zrP0xENE~ZI?*K);XODsqepYqAs z#oEVe63j14lLJH zMUsY3;+?Elbuz)4Imj1|41wCyXJw}|#7Od*pQ&4YY z!%NxrCa&tIi7E%<>QLv5r>pz2gaAoNDRBBDI}JD>ybJ0@h=&lsfU)ly-v*mcbW02BUPId+50lT z%}u0Sv$Q#whR;RXyQ(SMMW0JEIeqC=Nbb;&NM{h;c&OyZx7YD?xEa-;!m&*}1CMS* zC7oMsV{`jkPZ1@+AZH=OXN7^qyXF8;NefKIZuDe6YX|G^R<`X~&xvU1`D@&UKSL;b za>t*q09EHOC9v$j7Q58~sz2WEJb9_d(U;9S{4ZYis7tz&fvFE2!v3~Hr$?@U?bzuq z&*Guch-7{4w>JgUKW6-R!*$#!+DPAXTgZ@hBq*2aw)3o%tSpV6@-vNJJNj4jfjaB@ zn+>V*QE8)Ao=48qPEHk1W`$h&IwVE!5-hC!AoJ!k zBtKW?TGI#xS?x@(lkGc=W_Sy`BkkIBHD!-0aJjI)etW{U7rNr?3`+xeqO^_4M&uS- zy^mSJ6LsSkcXxO<40v_L9#psfvHHs{gh}K4PXjRW?j=s6JDJAHJ!;DBRbq!(@JvQ5 zC+ROL1sGjF{KlSQFX5>b_0qu7e{{Sb_}aC~jD=&$frpj1AC+BCP@IsA@T+}3<-ANW zIlFtN_6NVg@mop?#<#mY z((J^!yD_h(?%h%dWGXjBaX!=bJwdX%veCb311JmG;L z?F`f0E}sv!y84RBs$@=brYXhtd!^1c^$*tzTpl~g*sj=DWZEV(`Vq7~Gh0;C?Ig3? zjtHf@XQ`g)sY$*XU*wq4f6;^lTin?~wk4qz{VB29=tT+F@s!hc`wsYg*nkVCXZahx z2`iR)^0E6=CJXDz>Gt~Np~eiK>F-iipB0y^=q3O4^4u*$k%4Pt$!?_q0tSK&QzI!P4^D== z*Bv}+kr^6|YhG-++NYIylMRlCv4v06SlzBx>v;@vymp}dhBYm3CkB{$7Fa>QBu)KX ziRRD`0i-Ji%F4mEy;-glujh~X_p>#fl-nQF;as8~|GhI{&P)^`YJ6Fc=HJ$0X#TzV zP1gj7K{hebgOC>OP3~#XRrd_AzZHE^?q^Kx`>dT|{n?vOuWrSySB4J8sm+BaqF7bl zpNr1Q8HqHJFT6iuxP9=Nz9($hjy5{>w7NifI8*UpK(HsH>PhxzMLQpi$NXhWez?|n z8orpW00u)0*L3Mnei1r%^2UIdb_2eCZLbtEF5^DhTSttJAL&G9rCM|C412nD$mxp| zrdaRQUB3~37&hxNj#tYJ-;zcyJLbM#sXlVH^2`nZ-%i93DZ;2;0F}s&`z_=iU-FmR z=COJQpTp!;nAg1;^4v8mT2qre1KSn&dlh#aXpanCxY}zE+oX zXkIzIY#lSZL1)pyRKLS>$ql5Nm{;~})WwctwBn^fb)A%wf5O@Gh|)7j;=DSPh5`Pr ze1>z&8Kt%-${+02x#qfAHe6rsXom$!LX3yuTlXEuNZ*oF?=yx|yJd52ZZ{qB+bKDv zNGDE-E8H59UG~k|SaYy1=#g~XD^bsVhACS_zHljg8V!og?zH?>vOU&@kexq;Wv6N{hb4vE`rV`K@B$t-n_zaz%(4oZ9b|MwY zBdx`y@hGkhKJgV|>uTovE6jKkZX6I<;;JZLDWSP8=Ae{=q?6V)GZU`YOR~obJ$>S& zpY69i8SVY;WqnBjTy*Zr#(uqO+t)g7ay`CP@mkLgMM)Gj9rrm?diujYmvpg)A1?z7 zMzo|<83ZwRSuKX32B3*GkW*X4U&J9fsUY;g((i8W} zZbTcst?@QK@MN#K9c614vv047C9u3n{N|R;*T27-G9jJY7cc*+KVruL@vp~>6~fL8 z@2Tt9>iV|NOVfngJx1c1uS3p|P^0?}^~)Jv7qf$Wzf1I2PtkGA6%IcdmUC~l&!5!4 zcAPt2bnMC7?HQdn$0~I~7HfGLz1Ds>^|&aewu8K5T0lbD+t=5kYP%TE=R`aEsBan~ z)%{~dlf_55iH90kUcE$^EIKBTHu6HnW6MB*95wnvCrZ|&V(xUev0*D_)nL~0+J-tr zQ%AlMu8_B{^q_=P-nU7Edl8KaL-LQld6*_I-7F}dFPE87T<R*EmNFxb=w5+=?Wb1}gUHv;TI`=v5Em*D!M zV9rBFfRM8B^~4pE3Sl)LhY+03t4syWi45ny>41P5;BKP~s$N4Hu)HJ?GnO#SXToOG zYXaZySmoPLcB80CwZ~dE`=y^i)y-s&5k$d)!%s4Bh-A5(%X;{bvz_y~WALc7oq6); zG{%C&KZ;-+Px!Ivt$IdDbHw$Y+yPc6sR&6Mr`vSf;P&v^0$pHbWZRCQjWXnCA^l55 z<4+3tEBQr?5r`!W~XQ`FIiSp0eE)Nnq_g`UCb`V$)h7Nnu6Xg=_|k7Yi4p; ztia?e)Gl)lB)#Es=gb;TD$ZzRi%-FVeF5eo(*%CKEJZqNSu3rk4lc(ukL1O!TR+s) z*&8W7j zOS`5^K0Wy4O}5e*n`c=%zS?My`|=VYyg<>qWAw@#+kTTWG2{DJi&26?=^qm`ZPP=3{mYG(4 z+R;XennQL*=I3oJ#$Cqz*$RAx< zlfGPjir2!;VPbR3eRbvlSau@Ozb$9=d3}9Gid)}s*bwQJC{IYzbgBaVzR@p#LG!#( zn1pJwMCq)rW{|?SeOaLS8R*NHo_n@5xqLIsIMu zeAZB+OS&R|c3sC3zw|~+gA>}Zq*UkqH~O9yB2Yn;D9q4w#Ez9+{RAma<=rnmXA$P^ zcQZt5ZK;vh;zgIp%ZlrdEZZy)o6ITMf1pqIRY@JJ^f2HNmgTlQA##+X#v#VgvU`-? z?rH>Ue{kJRmzjpHyZXXYYk4XxbDe%noJn?Z)E8zx+h?+B$=Y6%>Da)HYcuxM4U2y6 zOpXwYo$Dd(iqVte=(BF@cwAduJ1Ustx`nPPGs!C?J1Cmd&{K3qKF+V$?MDCjAbjme zyr2GL`xeuX5-(7dp5u@1ec>wYJ#kv(TB&=UIoW7jV5(KG%ROG{@>FT2>Su%VafE24 zy?W{Q{Zi8Eo}Xbcw`*7HGwFcYjIa55-Y^iyKU#45!_ynnCdDaN?NrxLn+w9?AmrcK zdg|?}xRc;8!?QKdX-^aNI4>dm!+>=g>KBk+TIorqL zt$#WCjb3$swoLNqfnMNlFY|HUzZ}xCj^EYcTP$q{Rq%~GmNrpWrX`7NmwTd7Eq z;hvjhkeV8M7KK-T?>BiZ=3BgSp!adLNu~~b+vdo4#LV33>xWK4ol?;2o;I6tV`kL5 zCs!*{SUoAtZ>pHoad;|ON@8?eA>L3TPD5>O7$a(b2aC-Ql|Q68#;DV zirn6-=?|J*n@UxcKkyJZy9?S@NBjWxJg<1!8+y%Y2ZimC^w6iMagV045C7&2SDE`5 z8zvuZyzJ05Mj!tTH?5)Lb7^Gm?d1LMl*RJ1nj&GK|1&RSWg4CaQe26SuhgPjM+25? z3Fj;kbROF5TA6UqVBMgx$)gKrOdEBam&UKNSF+M$kkI)EvUozczZ$gpP7gY`x#j7^d_$(5FFZ3$)mCh}wYh73jiN!~ zLu-!~)8{^^&65TPHnsd!wueRUaEZV6D0#&vgttfvWF&ntUOAeo6PdO77N`BWdJB;m z{p&#+ml?L?q$aSCvKtNTb$L3A(_PAtK>{4{Jp;@XC5uvzALh@ah>@2{IU@8w5qOu46FxW`aUt>d=#(y8o5B zClGg+r)PrIPL*s6!c`ycGw{30(SSLX|o z0*In?vl%CreDmi7? z%y(tnt3f>+oLoMA+C$<);YKW@Ixq`^yLC$-XbM zf;|+Epiz)Jz9_D&fr-0F71 zdS@4ixSb!u#k3^J;T!joy@8CD*g+7a7q%yAF9G1988V?=8&uC#@bU7NI4SnPGZ}j` z)**b`Qe@_&|F0vgVO__6V{BG)(W!S%0!>gb2R+O3`YxT;lqx>PlxVSzc+Z0Uf~Uw$O;c`fw54iY$>yu7 zChwIN#_NrS5tZhGy|fP&%$8hHJ-ubnGkho`JzM1sxqib^p69Rc zOdRrz-7i?&L?*9jeR2FiUq-}tRkrg#?`{)PUAO*LT`wj2cb~7_HhZS{UPnJiU(hu4 zA9p88w53*WD^7L^XAVHVA>~#iZ<|5Y2dB<5;)5xUVd$ zF7au7SF>k$$j3MdDWs9vd}t_n37=;4Ua4<3;Ss(^-Q1emonDI_ojy7X9P9pT@u8k& zx?~gQ?`PNlOCp&>ei7o^8=L}iQ{X+Z3r-?9PfH_)`Ilf(Fsp^_on)!*nO?7%% z9OY3#K`)R+J9qb!P2v+_Rzo5AsvMd*>DC}a5sRvnJ|&PEZR@yi)5|X5|GQPcZ2(*( zH!G_XSlT^Y%P1uv@42hw8{9gq#PB5IwTZ`@gAbsHw`@Kr#^|w?Z2LCGO3z=7D4yZE zRi5`PNQQium_0tboo88G*~oqOh*tw3G`ZqCzFEJzfGY%FR~(^qKKKY=TTO|88`{^a zMJiLS=BlZw#h*=S2aqz9l$^}1AQNtQlkGeVB5_?*^1o}6_NcJ1@O~6M0p>Rn;>CX| z?8}6idS9LnVXD2R{)vOBZk5!s&t&%DGnGf%27B~)B_iMIYUYUu>|j2inQqf8CrB4= zs7s!Lh<+*BfcN^=;eMA#kOta8wiV8Q1KQq%*!^^_7wjTF!?dH?spp*<>C5S+WJp)} zIaeh{H2RFf5R>$dk+gOg1lKOwqJC0yGRD7Kca&^0qZ_Z~Qkv%Bl>s?cdt#6GV)$jy zQh`!-G|_y8N9s>0XG|MbamQ3y#ok}L0EizrwFLH$oa<$2yT5p!#79LUTgb%fp0a~I zn)ip-8uE=CF8)6CF{%0s>^^k!-P?2&AOB@eN+F|};WGp*Jp;nEc*=19{Wp(t!2x@p zTm?=ubU>(Qo&2HxwR4a$;u$Yr$aOYj<2ot+_zYj;wH|8%c?#x1LT6KAY*(`=WE_5M z`;Z$1SK0#G@yDE;cJzm7zwkjDC#Nwp8moQjWZM(kD#}~9-+M54cPa|XjYh%zb6lb$>ZD6%T$Ln|)VoNiFqpRFQW-L^_lD$M^3A;qeQ$Q=a0n@Qb zLELY-@p>Q`Hn5xu#%VK)x;9?}0pNk(1b|BBov@uzW8|-1wdpL`4+))x4&NHLXKWob zN$y&um2uSP9$3t9+$ig$9jmWq)mZG~w@5SrmcO-AbI(WXJ?=whF6oFw?3Is>xt+N+ zQXHaVuSN``RzzvFzz@;=Fbs2=r|+JGVM0aU%qER^zX;##%TF>vP~`M!m}H^*l-?!X zwIgjVu0XB1c@b69}}erZx5Hk7668QAEU-SqjJTSOEobH zy@Qkd1J=E=MmKi2;R%VkI$2;*vd=3LLO#d`c^0WFu*<%@pKSD6v?yr`pRAH8GP6o6 zOjm&&_|Jp5zPZEZcF}u==3KikLM$rrmsT6g*N;l%*{*dy&OaxBZ)y!mn?GW9$^EU0 zM0VG(o3j1&jCrdE>q;qWZL9%FDuie-4oso1tl=Sb(2CMlBA`(G7!+U@BLY>dlPy++Qs+Rx09 zO<2Eu;Ar3dd^p~vs<7!!CNj2!Bc?6^cCbof)tWJ3TwDcIQy!Oovp!Jy-OthEO_+_5 zel$B6sAbO$aLNML=)`KbZ+iJM(!*%jke(Xh4l&hqY{f^>SYZwHN#1Z^oXo8 zL;A0jLH!rnTXI>a#Gh~du6v}Yoj~UJs!PliFU%7zI@H*ZOD%0-rJ02H zc7wyD3**=7ogg6Nh#EvUT*8@fPNS$DH=9tP^GG7F3Vto1fPef~n4;BD)-Xsty(0UR z{Dm5Se^A73ABowEjBff4EC%uSnp#-a=59!2iW*q*CykJc_0ntjDhr$%1$Z<9V-M zF+2M|qel&T!S_V1`b{h?-B)e35W;aNE=3y0A(F(KG|m8dR4uJoNyf@kIdw)StLUCG zg-JX@Z}DMX7L1kBe6nv#9v<`u*>Xx1_yLbG>IWvK%`je0^HP)a8H6dxJzkf4b*yM$zJD+pxbM6z}yp#DP@CepODtn-BRI5^lUo!<%unkHSjrB;>b z8vE|#U6))FvD9*q)D>Z~nL4I0T^KQfng2#XTzJ=SB`D2{39pA85sjyIwYRiH>i)!i z8vR%WGc;cqp$KHPm9RL<)WTvTjw6Q|lNnkar3Wf9r92wkOk5jv7GpQtpJ4G zKv;`4H6=|K##)R%+Jb=w62T@0gCbNs>fmYDJYQJypx*@p1b6NPZIp-4grjS2s8jGX z?Kk$~f13F~xH%sRh+e-6%~186yVlV(Wq*POosQLU0_q_rB!cqi3C&h4#1NHQJ9zf0 z6AkI<=?7A>sCYI5Mt?ExA)$Hu0_L%xkbyU1AgfADWSzc#eI;ICI|)77g=2|GR#H+@ zTYWvpzlbJ3hY~r_kV=(O&*N6?iDf2cP}suRZYGgP!MICHPzJjqvJ7E#Xg!y(@ULb~ z+m9dKoD)W<|6mN`z(?Ou@;{`Z5soJrtlWfXWL;s;MhFgQZw~RlyOgw^i2$Ysvt%aeP}e=k&VIU9U^~^j7kp3R41^Yu zEMSe=;S1Q7_&;OEmIWb=?PxtE!39ua8(yf2dW+NvHd;?c^u|L{g6SJu#1oXbP)|U| zZ)khA98%ddF@<@0(O15G8)0fnwQpE{fzy@=ua|(tiYQuOA z%7+3pVDE<~wycA&a4D$&P&F>JQZdu1b;v?0{IMK8B>w%>wbL}|Z_KDfs>v7Y;B(vcc@s+j!i?%}}hW zP{Thu&qMPhwD!l!GActJ{4nW}Us9rhOHka3M1X|@4Wt54a%NCH>pf52d|`nfgPKsw;;mzI{cjZyg!wZdKSJ*m-!xiP1Wjk&_EjRSyIo?$~Pkj4P4hMWf| z0o~9Xj76sxy|Nu^SPS9_SE-(md)}UAeFfu6$gKX)p~W4NlAmwfxS>p3Nxj;F1tb(s zMg18W863Dv>#)HbbdTmw)Q0gKpaQ&xx646!r-ic)On)m<{U_e|aR|*Uj>DTW0aFo- zdnbw#G}QHqH0xgCV?5wl#>kKg6{sEJqya1>V6&OuMvG+e0xBiwyQfY`(F!`m^>`?d zso+`a=h6>K0%qA0%>Th4lG6>)=nG z5r%AatTw#E24tu_qvPFE0A^nZ^@=#5IZ8zR@Cw>22~!s*Y-?SN;xY%NoU?0a+A*@q zxcL@neqq-GTK$_uFmHM9kx4eDNC#rxC`2=1)c;xo+8B=@ASwxikp&QdcW!I@N=!^_ zIreD6Yo zrao*ogTN-SruMcrGrdrpayVK9EXX*)FzQe6tnpKmCY^#=lScDh_aRI#z(fa>`o{{I zLzV+rOl0)}H^GX5|1(<%e)8`L9kX-;=YR3S0cPy1dafkP?0+AW2H`HK(Np)g(maU+ z^exW*NVy#y<4&Pa=n2xJ=-XT{&_F5xeNdk*dXc{L!&~O_tmVzO79DeN5Rd$E7l_(C zY(Qp3Lqobs?V3%d0A~MRZJbf7f3C!*m)+k}T$_rjKa68shC?%1{?|4-`-#*F{8&i=H{{6Vzyr*($z zxBrDE{)>bGEfu0T`qMgtUF{2sg#NV7*oD{sX`Ma%|4Qp@V($Bpu!=q}6HYjubY^J4 zZ_!87r)Fok;(8%zRlbo)x&2J4k zAKK8DfD0E;y1e>oGc@?9KjV-4`NRMD3w-K5-maN0+a&#AnI|robNl)SY&N$z1PK56 zk^jeE81P3~(vsd8x~4NU-8D_PxcpMo>*qZG_iz36k*q^jZFJwpoEKMSE!xkLwpLu{ z*~Mqw#1ukC$f%Gi6DmjG6fO`EBtR zx_EWHlF%;TfdA`Jf8LZZXKxK|vNy6jM}E;W)-b6@%F6{gWNrpY(mEom+hz8Q%6^NL zi(Q$f)*3JT%i_qrIGK+H#@Z3b(pHHa*?%Nv=YxH;eo}O0 zEuL~-54pV0)f=Ttz^wl1M~Qw+#~9dU2+@h_4+JX@IBzsS4DcU+G7;~?k|uB7@FTsy zi0|myfanJFB=)lGq;=e}`w^RQZ8mHjbPLwSy_`g@aVq*eH!UO6S|65M)?buSWG3GD z<%8VJ+0tWjk6kWL4obV%ka9=o4)6Vu)YEYyv&VURX}WsN-Hg!T$flcSf)CW9hxusT zg_VUsE8-NXs2dqA{Q5de79BfDl=RLbc3RM#OkvP zdX1W=!L&Xhyu2Wau0FqP$}yjmK_=lV&sm_Rpj;k7^CRp9`~evZO^;1bzo@C$OzSme z?eFwmTxl;bfcHNJYjE$R>3x*Y;8C4$KLVGDzY#UpF&vnK>&TY*`iPerWuMThybTMw6+zZG65B zBaS)bk-}RYO-a@o1}{hVHZSVXL!ImS_Z2n95#sKmTS(p zCt(5$kfh96(yWV7AG>>LCC%`e;?HHYH35CZpoc%yY1!uwMS(5;&2-;HS1z2IdQGin z`Xaj>^~qzaKe3PA#Q-J{n<+18amYV<7q486roR!4|e}pFZrCo!jLl8xu5XZ|~Xd;^R$zSklFF$^4u5IE@5IhabU% z(>2=aMNo;uTP2N&9fFn9HaTb)%}BZG!)pUE!^&(pMhW8WF$C|y zrD5lu#GQn^*1@wAg)RRwXlg(_Zp9}o@Zbv_Sa*-Cnl-~;S%Xk1h8*CBF;=>^!Y+!!FX~vUm zzU!OY5hZ)LkT}xg^nhkY6kV~}-QRoWF5Qj+TpfN(AO=$|W-u@(e|pDn-ztsGzclH( zn(!3QVuOy34s389l7d`O(&Ru5?!lsC)l{VO`A7&Y!!z1=x|OazhEB(kH$d(nhGz!s zI4(o@p3f^l87q?J3pKIY;D!N~uqyB$sp-kVD+jDb&h;8-zG%cb;y&Uj#>y{GO6*Os zfdxoXCRVZ()W>=brP27cba*ues7u$O>A^DLvm>p9)5(uFrh{_MI%VP1MCia%G|3Wv zq@s)$s{>nUxwniQCeN^2(Vk$$D-VSCJPM>`0Jm0EA`U|8 zM_md7!YmlZahq5z;~&T^d&PjFf_W>dZF~W~6H<$gO;~m0rSl40Li5o473uq3!~Ets zb7@eC!5eEr{i^1+(K=e0>jv|vSl0VTiaGo&0*YY}$juSRIDa5_u=a-!&9)AvQpQqo z-(t~>&R@T61FefN(+?q~uVg0GM{*vh(n2Dl%L`)YvfCYAl-Ix!y+e}F{6*)NymzC4 zvAg}IAs4YK#9T!mcxQ^ydRq6w#e9-DhDQNFiSp|Xn#o5Vxo0wz%^8%`*PnOfJyn%| z&-Tf1FVteBxGYtgY>6C2_f4h?7X8%_n6k$O&MzX?m4R6gSG z3s6J_i@GRK&mU&I2&Qbduqh9TWdS2nGkdbNi5ruD`7#USa~Y8-xl^;V*r0uF4BfXn z$tr8V#TR)6oY8piCces!rs3@%wz7uJE)Dafu#ZY*V|eD)?&1!*?9xG;aVEL(>)E&X zEe}vHm>;6JF-@_1$;Dt~u4D+m>S!#5F{=U@8#RJ31=LhAKT`muwwwQ6H4JHLip$6k zQn+cOt8B#{dRZ(O8L^qHOhB@$lX2lA=r!hrU;=hOk!I?La-XTMzAwGc_HmB1x(-Df z+V#zqpPf*zDXp@o={e$SdM8@SoWDadeQTl8k(+xvWNE(i#{{S@b4~P7H^P80%X}Cs zYw>myR+$V2;;0+VUr~K!A1$xprjnI|I2HPZE7C7{9&^2sGuHZKS6~uys1#K7GiF*f zY?fZEBXR6KZ{&;-jyvFC*{i;VgZF8fMG5es4hKW?Ohbk+MruJDc0q*JMYIG?%Oj<) zM=t6YF(LZ2kcic#vYDk}gKjc>z8MS#)o9|G|A_LdlH}=&CtD%^0K*)N29GF}=Nz=| zB}aeO=<8?=X{5Sn2l2U&UmcRL4- z@y>-tG)ajYOWNH0N3H$eng+(!T*dIrfE{O8!)ELmD?N)duDponGP;DK!3AK6Vr^ja z$YdHe=Bkx$$Im(%3$y3ORD_KhL6`z%^bzN03J3;J+I1PD@NYrZeyTyTsv|Xnvb|zm zFBV*k*bI=ofL`}7gxy6u1M|Z!Ckl-liJ;khTA*{MN5uoZ*P_kVtc9 zUatSK{jQmHy;U9HuD~!`ccBk_X!8x4EYo?siB+*bN-J%x|F)Y}!ui66+_P&3oI;&rCA{DxliLD<46t{rSm;G=?T>sK6G$(s1DX z`HO_Gbmp4jOIM)#2#5H=T`uO|VV2z1!HTCZ`doA{<+sz0M9Bf1ak>F8AvlzQo8NFA zFc>rpkcxogs}@6evz7k{r zW1i_HrKQ;5JR}8g7xj^MF?2^5EAOH)et!KxXWpU&`9%rup#gYBbm3

^SW1Kj0`s zXrj2f?&ZrZQystnOMpdt7F}bFk-1`}c5ShNg>1#zTx@g*umk(Bumjn6DCcT)u(9?r z88)*9AgI{Rs!)Rg7b7+!JwO8VS|Q@!<&9E=^TICZTvE}c?ZoLA-^Z3a;OnfO|F2C{ z=t+T7G@@>V0ac#vpxg1Vj7P57j(8mlk-e9G<_kztP_j~nz(H-I&a0nzZ2w-q=){~c z@ch6YV9`-Pv#QuV@Ps@U;er4J@1li+cUv{C4?0}=t@>n&K3$grwZETmm?mSz$<)RM z<*uCtH5OPOy-tfQG+KXJe$g@5gBlnEN0fsmo_Pz+PWzlbHU-Do?~s4MHw4k(VXgCE zKP_fSloNy_3|NFCaL<|3Tt?<({hP0kpE`ft_c4D(W_P(vk{2y@6e}Z&_6JR^245hc zf+~$6p~pV&s|BK#8Y-{_uwxA1{KdQim^yP@MuE_MghO0fIx>0c-(i+^huvIq8p+qN z#Sl3Ob~2G{z6iuOEQk2lVO3 zpaJN748t?$S9z5#I_3u=Ad5`Wr?2-J433~)Fh49AU>{xg-CGWu4h<-Lv}+5sGnPg@ zFQT)-LWdyi05v_#&klsGgmTW~1`7WcWa?)jZRdlaBKQoGCl*|c*bET6`K{YE=!AOE zl5t+O525KNy3{KVoF4r&6F&K+UZnefZK6U?$~HF@bt5dOa+)>l9z)ZYCl)MeSjg*7 z>v{tbNeUwLX`u^e!XUQ%Dba-54%h=MItrv&RV*Vh{Q$Rv-iCM`gM6;jZLu5PFE3YH<1 zAT_+3|4HKYatt`+J)V?7`8p7qXCH;lzmjoIc0`bzkcNjHvB7yr3jF2`-jJo6>2_G7 zF@ApiK*1ocuLgDsK+{hU!!rYRoaPmnhStiMr#WxvL9r|jRC2taVwdef&xkRm))qqH z|E!&{H0lQsoed^B1lWNvEbKrU4$8S4D*RiJsZX|xECuP&(O|_|XAHO)u^AwC0ll7K z7Lc-BxU&Y`N)%lt^2oI%^AF#A6L?c&`~TWFJ%%`izANfR7*J)KyZ=&D0Sa10EaWwt zg8UDVq#y)k)4!8wLiL4FM*$70;r4s)LK(u=DMRqaAfLz|sDR(0c(VrZ7XGF6xe}kzFWW5ggpFZ@!5uHLJ&8~S1&9kkirW9-Ml!Ch=ta2q9 zJZ|fW(iB^=Ai@zkEW#1EXG+OW;UBl@;Y9x7z^|mqFIW1a|5rv7PR|eiOg}(C1uBif zA^-$(mKrLs1u$beaDGQdWh~t|xRDRgafCxGANH05;n%;wEPuvI{*0CU4%_~WmHZhi z`7>7Xw@3ULD_Lk%@6T8XHaP!htb_&uVfAOM Date: Fri, 26 Jul 2024 13:50:40 +0300 Subject: [PATCH 07/13] added tests for checking archive page with default pagination and category filter with different permalink settings --- tests/e2e/specs/archive.spec.js | 620 ++++++++++++++++++ .../archive/expected-category-default.json | 116 ++++ .../archive/expected-category-post-name.json | 116 ++++ tests/fixtures/archive/expected-default.json | 226 +++++++ .../expected-post-name-permalinks.json | 226 +++++++ tests/fixtures/archive/portfolio-posts.json | 88 +++ 6 files changed, 1392 insertions(+) create mode 100644 tests/e2e/specs/archive.spec.js create mode 100644 tests/fixtures/archive/expected-category-default.json create mode 100644 tests/fixtures/archive/expected-category-post-name.json create mode 100644 tests/fixtures/archive/expected-default.json create mode 100644 tests/fixtures/archive/expected-post-name-permalinks.json create mode 100644 tests/fixtures/archive/portfolio-posts.json diff --git a/tests/e2e/specs/archive.spec.js b/tests/e2e/specs/archive.spec.js new file mode 100644 index 00000000..17db8d1f --- /dev/null +++ b/tests/e2e/specs/archive.spec.js @@ -0,0 +1,620 @@ +/** + * WordPress dependencies + */ +import { expect, test } from '@wordpress/e2e-test-utils-playwright'; + +import expectedArchiveCategoryDefault from '../../fixtures/archive/expected-category-default.json'; +import expectedArchiveCategoryPostName from '../../fixtures/archive/expected-category-post-name.json'; +import expectedArchiveDefault from '../../fixtures/archive/expected-default.json'; +import expectedArchivePostName from '../../fixtures/archive/expected-post-name-permalinks.json'; +import portfolioPosts from '../../fixtures/archive/portfolio-posts.json'; +import imageFixtures from '../../fixtures/images.json'; +import { deleteAllPortfolio } from '../utils/delete-all-portfolio'; +import { findAsyncSequential } from '../utils/find-async-sequential'; +import { getWordpressImages } from '../utils/get-wordpress-images'; + +test.describe('archive pages', () => { + test.beforeEach(async ({ requestUtils }) => { + await requestUtils.activatePlugin( + 'visual-portfolio-posts-amp-image-gallery' + ); + await requestUtils.deleteAllMedia(); + await requestUtils.deleteAllPages(); + await requestUtils.deleteAllPosts(); + await deleteAllPortfolio({ requestUtils }); + }); + test.afterEach(async ({ requestUtils }) => { + await requestUtils.deleteAllMedia(); + await requestUtils.deleteAllPages(); + await requestUtils.deleteAllPosts(); + await deleteAllPortfolio({ requestUtils }); + }); + + async function deletePortfolioCategories(admin, page) { + await admin.visitAdminPage( + 'edit-tags.php?taxonomy=portfolio_category&post_type=portfolio' + ); + + if ((await page.locator('#the-list > tr').count()) > 1) { + await page.locator('#cb-select-all-1').check(); + await page + .locator('#bulk-action-selector-top') + .selectOption('delete'); + await page.locator('#doaction').click(); + } + } + + async function deletePortfolioTags(admin, page) { + await admin.visitAdminPage( + 'edit-tags.php?taxonomy=portfolio_tag&post_type=portfolio' + ); + + if ((await page.locator('#the-list > tr').count()) > 1) { + await page.locator('#cb-select-all-1').check(); + await page + .locator('#bulk-action-selector-top') + .selectOption('delete'); + await page.locator('#doaction').click(); + } + } + + async function getArchiveItems(page) { + const archiveItems = []; + const items = page.locator( + '.vp-portfolio__items article.vp-portfolio__item-wrap' + ); + + for (const item of await items.all()) { + await page.waitForTimeout(700); + const url = await item + .locator('.vp-portfolio__item-img > a') + .getAttribute('href'); + const categoriesWrapper = item.locator( + '.vp-portfolio__item-meta .vp-portfolio__item-meta-categories > .vp-portfolio__item-meta-category' + ); + + if (await categoriesWrapper.count()) { + const categories = []; + for (const categoryWrap of await categoriesWrapper.all()) { + const category = await categoryWrap + .locator('a') + .innerText(); + const categoryUrl = await categoryWrap + .locator('a') + .getAttribute('href'); + categories.push({ + category, + categoryUrl, + }); + } + } + + const title = await item + .locator('.vp-portfolio__item-meta-title > a') + .innerText(); + + const description = await item + .locator('.vp-portfolio__item-meta-excerpt > div') + .innerText(); + + archiveItems.push({ + url, + categories: + typeof categories !== 'undefined' + ? // eslint-disable-next-line no-undef + categories + : false, + title, + description, + }); + } + + return archiveItems; + } + + async function createPortfolioPosts(requestUtils, page, admin, editor) { + const images = await getWordpressImages({ + requestUtils, + page, + admin, + editor, + }); + + let key = 0; + for (const post of portfolioPosts) { + await admin.createNewPost(post); + + const foundFixtureImage = await findAsyncSequential( + imageFixtures, + async (x) => x.postTitle === post.title + ); + + const foundImage = await findAsyncSequential( + images, + async (x) => x.description === foundFixtureImage.description + ); + + const featuredExpandedPanel = page.getByRole('button', { + name: 'Featured image', + exact: true, + expanded: false, + }); + + const isFeaturedPanelExpanded = await featuredExpandedPanel.count(); + + if (isFeaturedPanelExpanded) { + await featuredExpandedPanel.click(); + } + + await page + .getByRole('button', { name: 'Set featured image' }) + .click(); + + await page.getByRole('tab', { name: 'Media Library' }).click(); + + const imageContainer = page.locator( + 'ul.attachments.ui-sortable.ui-sortable-disabled li.attachment[data-id="' + + foundImage.id + + '"]' + ); + + await imageContainer.click(); + + await page + .getByRole('button', { name: 'Set featured image' }) + .click(); + + const categoriesExpandedPanel = page.getByRole('button', { + name: 'Categories', + exact: true, + expanded: false, + }); + + const isCategoriesPanelExpanded = + await categoriesExpandedPanel.count(); + + if (isCategoriesPanelExpanded) { + await categoriesExpandedPanel.click(); + } + + if (typeof post.categories !== 'undefined') { + for (const category of post.categories) { + const isVisibleCategoryField = + page.getByLabel('New Category Name'); + + if (!(await isVisibleCategoryField.isVisible())) { + await page + .getByRole('button', { name: 'Add New Category' }) + .first() + .click(); + } + + if (await isVisibleCategoryField.isVisible()) { + await isVisibleCategoryField.fill(category); + await page + .getByLabel('Project') + .locator('form') + .getByRole('button', { name: 'Add New Category' }) + .click(); + } + + await page.waitForTimeout(500); + } + } + + const tagsExpandedPanel = page.getByRole('button', { + name: 'Tags', + exact: true, + expanded: false, + }); + + const isTagsExpandedPanel = await tagsExpandedPanel.count(); + + if (isTagsExpandedPanel) { + await tagsExpandedPanel.click(); + } + + if (typeof post.tags !== 'undefined') { + for (const tag of post.tags) { + await page.getByLabel('Add New Tag').fill(tag); + await page.getByLabel('Add New Tag').press('Enter'); + } + } + + //await page.waitForTimeout(500); + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Project', + }) + .first() + .click(); + + const postLink = page.url(); + + portfolioPosts[key].postLink = postLink; + key = key + 1; + } + } + + async function createArchivePage(page, admin, editor) { + await admin.createNewPost({ + title: 'Portfolio', + postType: 'page', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + await editor.insertBlock({ + name: 'visual-portfolio/block', + }); + + await page.getByRole('button', { name: 'Posts' }).click(); + await page.getByRole('button', { name: 'Continue' }).click(); + await page + .getByRole('button', { name: 'Classic Preview Classic' }) + .click(); + await page.getByRole('button', { name: 'Continue' }).click(); + await page.getByLabel('Filter').check(); + await page.getByRole('button', { name: 'Continue' }).click(); + await page.getByRole('button', { name: 'More' }).click(); + await page.getByRole('button', { name: 'Current Query' }).click(); + await page.getByRole('button', { name: 'Layout' }).click(); + await page.getByRole('button', { name: 'Pagination' }).click(); + await page.getByRole('button', { name: 'Paged' }).click(); + await page.getByLabel('Close', { exact: true }).click(); + await page.getByRole('button', { name: 'Skin' }).click(); + await page.getByRole('button', { name: 'Caption' }).click(); + await page.getByRole('button', { name: 'Elements' }).click(); + + await page + .locator('.components-base-control__field', { + hasText: 'Categories Count', + }) + .locator('input.components-input-control__input') + .fill('3'); + + await page.getByLabel('Display Excerpt').check(); + await page.getByLabel('Excerpt Words Count').fill('20'); + + // Publish Post. + await editor.publishPost(); + + const archiveUrl = await page + .getByLabel('Page address') + .getAttribute('value'); + + let archiveID = await page + .locator('input[name="post_ID"]') + .inputValue(); + archiveID = + typeof archiveID === 'string' ? parseInt(archiveID, 10) : null; + + return { + archiveID, + archiveUrl, + }; + } + + async function setArchiveSettings(admin, page) { + await admin.visitAdminPage('edit.php?post_type=portfolio'); + + await page + .locator('#menu-posts-portfolio') + .getByRole('link', { name: 'Settings' }) + .click(); + await page.getByRole('textbox', { name: '-- Select Page --' }).click(); + await page.getByRole('option', { name: 'Portfolio' }).click(); + await page.getByLabel('Archive Page Items Per Page').fill('2'); + await page.getByRole('button', { name: 'Save Changes' }).click(); + } + + async function getReceivedArchive(page) { + const pageCounts = 5; + const receivedArchive = []; + let currentCount = 0; + + while (currentCount < pageCounts) { + const archivePagination = []; + + await page.waitForTimeout(700); + + const archiveItems = await getArchiveItems(page); + + const pagination = page.locator( + '.vp-portfolio__layout-elements .vp-pagination' + ); + + const paginationItems = pagination.locator('.vp-pagination__item'); + + for (const paginationItem of await paginationItems.all()) { + const classes = await paginationItem.getAttribute('class'); + + if ( + classes === 'vp-pagination__item vp-pagination__item-active' + ) { + const activeElement = await paginationItem.innerText(); + archivePagination.push({ + text: activeElement, + active: true, + }); + } + + if (classes === 'vp-pagination__item') { + const paginationLink = await paginationItem + .locator('a') + .getAttribute('href'); + const paginationText = await paginationItem + .locator('a') + .innerText(); + archivePagination.push({ + url: paginationLink, + text: paginationText, + standard: true, + }); + } + + if ( + classes === 'vp-pagination__item vp-pagination__item-dots' + ) { + const dotsText = await paginationItem.innerText(); + archivePagination.push({ + text: dotsText, + dots: true, + }); + } + + if ( + classes === 'vp-pagination__item vp-pagination__item-next' + ) { + const nextPaginationLink = await paginationItem + .locator('a') + .getAttribute('href'); + archivePagination.push({ + url: nextPaginationLink, + nextPage: true, + }); + } + } + + receivedArchive.push({ + items: archiveItems, + pagination: archivePagination, + }); + + currentCount++; + + if ( + await pagination + .locator('.vp-pagination__item.vp-pagination__item-next') + .count() + ) { + await pagination + .locator( + '.vp-pagination__item.vp-pagination__item-next > a' + ) + .click(); + + await page.waitForTimeout(700); + } + } + + return receivedArchive; + } + + async function getReceivedCategories(page) { + const filterItems = page + .locator('.vp-filter .vp-filter__item') + .filter({ hasNotText: 'All' }); + const receivedCategories = []; + + for (const filterItem of await filterItems.all()) { + receivedCategories.push({ + title: await filterItem + .locator('a') + .getAttribute('data-vp-filter'), + url: await filterItem.locator('a').getAttribute('href'), + items: [], + }); + } + + let categoryKey = 0; + + for (const category of receivedCategories) { + await page + .locator('.vp-filter .vp-filter__item') + .filter({ hasText: category.title }) + .click(); + + await page.waitForTimeout(700); + + let archiveItems = await getArchiveItems(page); + + const pagination = page.locator( + '.vp-portfolio__layout-elements .vp-pagination' + ); + + if (archiveItems.length === 2 && (await pagination.count())) { + await pagination + .locator( + '.vp-pagination__item.vp-pagination__item-next > a' + ) + .click(); + + await page.waitForTimeout(500); + + archiveItems = archiveItems.concat(await getArchiveItems(page)); + } + + receivedCategories[categoryKey].items = archiveItems; + + categoryKey++; + } + + return receivedCategories; + } + + test('check archive page with default pagination and category filter (plain permalinks)', async ({ + page, + admin, + editor, + requestUtils, + }) => { + await deletePortfolioCategories(admin, page); + await deletePortfolioTags(admin, page); + + await createPortfolioPosts(requestUtils, page, admin, editor); + + // Set Permalink Settings. + await admin.visitAdminPage('options-permalink.php'); + await page.getByLabel('Plain').check(); + await page.getByRole('button', { name: 'Save Changes' }).click(); + + const { archiveID, archiveUrl } = await createArchivePage( + page, + admin, + editor + ); + + await setArchiveSettings(admin, page); + + // prepare Fixtures. + const testBaseUrl = process.env.PLAYWRIGHT_TEST_BASE_URL; + let fixtureKey = 0; + for (const expectedArchiveItem of expectedArchiveDefault) { + let paginationKey = 0; + for (const expectedPaginationItem of expectedArchiveItem.pagination) { + if (typeof expectedPaginationItem.url !== 'undefined') { + const fixtureUrl = testBaseUrl + expectedPaginationItem.url; + + expectedArchiveDefault[fixtureKey].pagination[ + paginationKey + ].url = fixtureUrl.replace( + '/?page_id=0000', + '/?page_id=' + archiveID + ); + } + paginationKey++; + } + + let itemKey = 0; + for (const expectedItem of expectedArchiveItem.items) { + expectedArchiveDefault[fixtureKey].items[itemKey].url = + testBaseUrl + expectedItem.url; + itemKey++; + } + + fixtureKey++; + } + + fixtureKey = 0; + for (const expectedArchiveCategoryItem of expectedArchiveCategoryDefault) { + let itemKey = 0; + for (const expectedItem of expectedArchiveCategoryItem.items) { + expectedArchiveCategoryDefault[fixtureKey].items[itemKey].url = + testBaseUrl + expectedItem.url; + itemKey++; + } + const fixtureUrl = testBaseUrl + expectedArchiveCategoryItem.url; + expectedArchiveCategoryDefault[fixtureKey].url = fixtureUrl.replace( + '/?page_id=000', + '/?page_id=' + archiveID + ); + + fixtureKey++; + } + + await page.goto(archiveUrl); + + const receivedArchive = await getReceivedArchive(page); + + // check Archive page + expect(receivedArchive).toEqual(expectedArchiveDefault); + + const receivedCategories = await getReceivedCategories(page); + + await page.waitForTimeout(500); + + // check Archive Category filter + expect(receivedCategories).toEqual(expectedArchiveCategoryDefault); + }); + + test('check archive page with default pagination and category filter (post name permalinks)', async ({ + page, + admin, + editor, + requestUtils, + }) => { + await deletePortfolioCategories(admin, page); + await deletePortfolioTags(admin, page); + + await createPortfolioPosts(requestUtils, page, admin, editor); + + // Set Permalink Settings. + await admin.visitAdminPage('options-permalink.php'); + await page.getByLabel('Post name').check(); + await page.getByRole('button', { name: 'Save Changes' }).click(); + + const { archiveUrl } = await createArchivePage(page, admin, editor); + + await setArchiveSettings(admin, page); + + // prepare Fixtures. + const testBaseUrl = process.env.PLAYWRIGHT_TEST_BASE_URL; + let fixtureKey = 0; + for (const expectedArchiveItem of expectedArchivePostName) { + let paginationKey = 0; + for (const expectedPaginationItem of expectedArchiveItem.pagination) { + if (typeof expectedPaginationItem.url !== 'undefined') { + const fixtureUrl = testBaseUrl + expectedPaginationItem.url; + + expectedArchivePostName[fixtureKey].pagination[ + paginationKey + ].url = fixtureUrl; + } + paginationKey++; + } + + let itemKey = 0; + for (const expectedItem of expectedArchiveItem.items) { + expectedArchivePostName[fixtureKey].items[itemKey].url = + testBaseUrl + expectedItem.url; + itemKey++; + } + + fixtureKey++; + } + + fixtureKey = 0; + for (const expectedArchiveCategoryItem of expectedArchiveCategoryPostName) { + let itemKey = 0; + for (const expectedItem of expectedArchiveCategoryItem.items) { + expectedArchiveCategoryPostName[fixtureKey].items[itemKey].url = + testBaseUrl + expectedItem.url; + itemKey++; + } + expectedArchiveCategoryPostName[fixtureKey].url = + testBaseUrl + expectedArchiveCategoryItem.url; + + fixtureKey++; + } + + await page.goto(archiveUrl); + + const receivedArchive = await getReceivedArchive(page); + + // check Archive page + expect(receivedArchive).toEqual(expectedArchivePostName); + + const receivedCategories = await getReceivedCategories(page); + + await page.waitForTimeout(500); + + // check Archive Category filter + expect(receivedCategories).toEqual(expectedArchiveCategoryPostName); + }); +}); diff --git a/tests/fixtures/archive/expected-category-default.json b/tests/fixtures/archive/expected-category-default.json new file mode 100644 index 00000000..5cfa8daf --- /dev/null +++ b/tests/fixtures/archive/expected-category-default.json @@ -0,0 +1,116 @@ +[ + { + "title": "bicycle", + "url": "/?page_id=000&vp_filter=portfolio_category%3Abicycle", + "items": [ + { + "url": "/?portfolio=portfolio-2-test-post", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + } + ] + }, + { + "title": "car", + "url": "/?page_id=000&vp_filter=portfolio_category%3Acar", + "items": [ + { + "url": "/?portfolio=portfolio-4-test-post", + "categories": false, + "title": "Portfolio 4 test post", + "description": "Aenean vel arcu enim. Aliquam sed rutrum erat, porta mattis lorem. Nulla scelerisque eu ligula eget dictum. Phasellus orci nisi." + }, + { + "url": "/?portfolio=portfolio-3-test-post", + "categories": false, + "title": "Portfolio 3 test post", + "description": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie." + }, + { + "url": "/?portfolio=portfolio-2-test-post", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + } + ] + }, + { + "title": "ocean", + "url": "/?page_id=000&vp_filter=portfolio_category%3Aocean", + "items": [ + { + "url": "/?portfolio=portfolio-7-test-post", + "categories": false, + "title": "Portfolio 7 test post", + "description": "Nulla tincidunt arcu in dictum elementum. Quisque fringilla venenatis nulla ut sollicitudin. Praesent facilisis a libero laoreet viverra. Nunc placerat." + }, + { + "url": "/?portfolio=portfolio-5-test-post", + "categories": false, + "title": "Portfolio 5 test post", + "description": "Morbi tincidunt aliquet velit vitae imperdiet. Curabitur ex mauris, pharetra sit amet varius in, iaculis at libero. Interdum et malesuada." + }, + { + "url": "/?portfolio=portfolio-3-test-post", + "categories": false, + "title": "Portfolio 3 test post", + "description": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie." + }, + { + "url": "/?portfolio=portfolio-1-test-post", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ] + }, + { + "title": "pesto", + "url": "/?page_id=000&vp_filter=portfolio_category%3Apesto", + "items": [ + { + "url": "/?portfolio=portfolio-10-test-post", + "categories": false, + "title": "Portfolio 10 test post", + "description": "Curabitur mollis convallis congue. Pellentesque vel lobortis diam. Morbi et sagittis mi, mollis vehicula dui. Maecenas arcu justo, facilisis non." + } + ] + }, + { + "title": "sea", + "url": "/?page_id=000&vp_filter=portfolio_category%3Asea", + "items": [ + { + "url": "/?portfolio=portfolio-8-test-post", + "categories": false, + "title": "Portfolio 8 test post", + "description": "Morbi id justo tortor. Morbi semper faucibus ligula, ut porttitor velit facilisis eget. Aliquam eleifend dignissim neque nec placerat. Nulla." + }, + { + "url": "/?portfolio=portfolio-1-test-post", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ] + }, + { + "title": "something", + "url": "/?page_id=000&vp_filter=portfolio_category%3Asomething", + "items": [ + { + "url": "/?portfolio=portfolio-2-test-post", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + }, + { + "url": "/?portfolio=portfolio-1-test-post", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ] + } +] diff --git a/tests/fixtures/archive/expected-category-post-name.json b/tests/fixtures/archive/expected-category-post-name.json new file mode 100644 index 00000000..2a179b05 --- /dev/null +++ b/tests/fixtures/archive/expected-category-post-name.json @@ -0,0 +1,116 @@ +[ + { + "title": "bicycle", + "url": "/portfolio-category/bicycle/", + "items": [ + { + "url": "/portfolio/portfolio-2-test-post/", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + } + ] + }, + { + "title": "car", + "url": "/portfolio-category/car/", + "items": [ + { + "url": "/portfolio/portfolio-4-test-post/", + "categories": false, + "title": "Portfolio 4 test post", + "description": "Aenean vel arcu enim. Aliquam sed rutrum erat, porta mattis lorem. Nulla scelerisque eu ligula eget dictum. Phasellus orci nisi." + }, + { + "url": "/portfolio/portfolio-3-test-post/", + "categories": false, + "title": "Portfolio 3 test post", + "description": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie." + }, + { + "url": "/portfolio/portfolio-2-test-post/", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + } + ] + }, + { + "title": "ocean", + "url": "/portfolio-category/ocean/", + "items": [ + { + "url": "/portfolio/portfolio-7-test-post/", + "categories": false, + "title": "Portfolio 7 test post", + "description": "Nulla tincidunt arcu in dictum elementum. Quisque fringilla venenatis nulla ut sollicitudin. Praesent facilisis a libero laoreet viverra. Nunc placerat." + }, + { + "url": "/portfolio/portfolio-5-test-post/", + "categories": false, + "title": "Portfolio 5 test post", + "description": "Morbi tincidunt aliquet velit vitae imperdiet. Curabitur ex mauris, pharetra sit amet varius in, iaculis at libero. Interdum et malesuada." + }, + { + "url": "/portfolio/portfolio-3-test-post/", + "categories": false, + "title": "Portfolio 3 test post", + "description": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie." + }, + { + "url": "/portfolio/portfolio-1-test-post/", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ] + }, + { + "title": "pesto", + "url": "/portfolio-category/pesto/", + "items": [ + { + "url": "/portfolio/portfolio-10-test-post/", + "categories": false, + "title": "Portfolio 10 test post", + "description": "Curabitur mollis convallis congue. Pellentesque vel lobortis diam. Morbi et sagittis mi, mollis vehicula dui. Maecenas arcu justo, facilisis non." + } + ] + }, + { + "title": "sea", + "url": "/portfolio-category/sea/", + "items": [ + { + "url": "/portfolio/portfolio-8-test-post/", + "categories": false, + "title": "Portfolio 8 test post", + "description": "Morbi id justo tortor. Morbi semper faucibus ligula, ut porttitor velit facilisis eget. Aliquam eleifend dignissim neque nec placerat. Nulla." + }, + { + "url": "/portfolio/portfolio-1-test-post/", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ] + }, + { + "title": "something", + "url": "/portfolio-category/something/", + "items": [ + { + "url": "/portfolio/portfolio-2-test-post/", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + }, + { + "url": "/portfolio/portfolio-1-test-post/", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ] + } +] diff --git a/tests/fixtures/archive/expected-default.json b/tests/fixtures/archive/expected-default.json new file mode 100644 index 00000000..6f7e2910 --- /dev/null +++ b/tests/fixtures/archive/expected-default.json @@ -0,0 +1,226 @@ +[ + { + "items": [ + { + "url": "/?portfolio=portfolio-10-test-post", + "categories": false, + "title": "Portfolio 10 test post", + "description": "Curabitur mollis convallis congue. Pellentesque vel lobortis diam. Morbi et sagittis mi, mollis vehicula dui. Maecenas arcu justo, facilisis non." + }, + { + "url": "/?portfolio=portfolio-9-test-post", + "categories": false, + "title": "Portfolio 9 test post", + "description": "Quisque tristique, velit et auctor ultrices, ante diam faucibus tellus, quis sodales leo nulla eu ante. Sed condimentum dolor gravida." + } + ], + "pagination": [ + { + "text": "1", + "active": true + }, + { + "url": "/?page_id=0000&vp_page=2", + "text": "2", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=3", + "text": "3", + "standard": true + }, + { + "text": "…", + "dots": true + }, + { + "url": "/?page_id=0000&vp_page=5", + "text": "5", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=2", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/?portfolio=portfolio-8-test-post", + "categories": false, + "title": "Portfolio 8 test post", + "description": "Morbi id justo tortor. Morbi semper faucibus ligula, ut porttitor velit facilisis eget. Aliquam eleifend dignissim neque nec placerat. Nulla." + }, + { + "url": "/?portfolio=portfolio-7-test-post", + "categories": false, + "title": "Portfolio 7 test post", + "description": "Nulla tincidunt arcu in dictum elementum. Quisque fringilla venenatis nulla ut sollicitudin. Praesent facilisis a libero laoreet viverra. Nunc placerat." + } + ], + "pagination": [ + { + "url": "/?page_id=0000&vp_page=1", + "text": "1", + "standard": true + }, + { + "text": "2", + "active": true + }, + { + "url": "/?page_id=0000&vp_page=3", + "text": "3", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=4", + "text": "4", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=5", + "text": "5", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=3", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/?portfolio=portfolio-6-test-post", + "categories": false, + "title": "Portfolio 6 test post", + "description": "Aenean consectetur massa sed aliquet mollis. Etiam elementum lacus sed urna faucibus pulvinar. Duis dictum nisl eget urna vestibulum semper." + }, + { + "url": "/?portfolio=portfolio-5-test-post", + "categories": false, + "title": "Portfolio 5 test post", + "description": "Morbi tincidunt aliquet velit vitae imperdiet. Curabitur ex mauris, pharetra sit amet varius in, iaculis at libero. Interdum et malesuada." + } + ], + "pagination": [ + { + "url": "/?page_id=0000&vp_page=1", + "text": "1", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=2", + "text": "2", + "standard": true + }, + { + "text": "3", + "active": true + }, + { + "url": "/?page_id=0000&vp_page=4", + "text": "4", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=5", + "text": "5", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=4", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/?portfolio=portfolio-4-test-post", + "categories": false, + "title": "Portfolio 4 test post", + "description": "Aenean vel arcu enim. Aliquam sed rutrum erat, porta mattis lorem. Nulla scelerisque eu ligula eget dictum. Phasellus orci nisi." + }, + { + "url": "/?portfolio=portfolio-3-test-post", + "categories": false, + "title": "Portfolio 3 test post", + "description": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie." + } + ], + "pagination": [ + { + "url": "/?page_id=0000&vp_page=1", + "text": "1", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=2", + "text": "2", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=3", + "text": "3", + "standard": true + }, + { + "text": "4", + "active": true + }, + { + "url": "/?page_id=0000&vp_page=5", + "text": "5", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=5", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/?portfolio=portfolio-2-test-post", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + }, + { + "url": "/?portfolio=portfolio-1-test-post", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ], + "pagination": [ + { + "url": "/?page_id=0000&vp_page=1", + "text": "1", + "standard": true + }, + { + "text": "…", + "dots": true + }, + { + "url": "/?page_id=0000&vp_page=3", + "text": "3", + "standard": true + }, + { + "url": "/?page_id=0000&vp_page=4", + "text": "4", + "standard": true + }, + { + "text": "5", + "active": true + } + ] + } + ] diff --git a/tests/fixtures/archive/expected-post-name-permalinks.json b/tests/fixtures/archive/expected-post-name-permalinks.json new file mode 100644 index 00000000..e5ab87a3 --- /dev/null +++ b/tests/fixtures/archive/expected-post-name-permalinks.json @@ -0,0 +1,226 @@ +[ + { + "items": [ + { + "url": "/portfolio/portfolio-10-test-post/", + "categories": false, + "title": "Portfolio 10 test post", + "description": "Curabitur mollis convallis congue. Pellentesque vel lobortis diam. Morbi et sagittis mi, mollis vehicula dui. Maecenas arcu justo, facilisis non." + }, + { + "url": "/portfolio/portfolio-9-test-post/", + "categories": false, + "title": "Portfolio 9 test post", + "description": "Quisque tristique, velit et auctor ultrices, ante diam faucibus tellus, quis sodales leo nulla eu ante. Sed condimentum dolor gravida." + } + ], + "pagination": [ + { + "text": "1", + "active": true + }, + { + "url": "/portfolio/page/2/", + "text": "2", + "standard": true + }, + { + "url": "/portfolio/page/3/", + "text": "3", + "standard": true + }, + { + "text": "…", + "dots": true + }, + { + "url": "/portfolio/page/5/", + "text": "5", + "standard": true + }, + { + "url": "/portfolio/page/2/", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/portfolio/portfolio-8-test-post/", + "categories": false, + "title": "Portfolio 8 test post", + "description": "Morbi id justo tortor. Morbi semper faucibus ligula, ut porttitor velit facilisis eget. Aliquam eleifend dignissim neque nec placerat. Nulla." + }, + { + "url": "/portfolio/portfolio-7-test-post/", + "categories": false, + "title": "Portfolio 7 test post", + "description": "Nulla tincidunt arcu in dictum elementum. Quisque fringilla venenatis nulla ut sollicitudin. Praesent facilisis a libero laoreet viverra. Nunc placerat." + } + ], + "pagination": [ + { + "url": "/portfolio/page/1/", + "text": "1", + "standard": true + }, + { + "text": "2", + "active": true + }, + { + "url": "/portfolio/page/3/", + "text": "3", + "standard": true + }, + { + "url": "/portfolio/page/4/", + "text": "4", + "standard": true + }, + { + "url": "/portfolio/page/5/", + "text": "5", + "standard": true + }, + { + "url": "/portfolio/page/3/", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/portfolio/portfolio-6-test-post/", + "categories": false, + "title": "Portfolio 6 test post", + "description": "Aenean consectetur massa sed aliquet mollis. Etiam elementum lacus sed urna faucibus pulvinar. Duis dictum nisl eget urna vestibulum semper." + }, + { + "url": "/portfolio/portfolio-5-test-post/", + "categories": false, + "title": "Portfolio 5 test post", + "description": "Morbi tincidunt aliquet velit vitae imperdiet. Curabitur ex mauris, pharetra sit amet varius in, iaculis at libero. Interdum et malesuada." + } + ], + "pagination": [ + { + "url": "/portfolio/page/1/", + "text": "1", + "standard": true + }, + { + "url": "/portfolio/page/2/", + "text": "2", + "standard": true + }, + { + "text": "3", + "active": true + }, + { + "url": "/portfolio/page/4/", + "text": "4", + "standard": true + }, + { + "url": "/portfolio/page/5/", + "text": "5", + "standard": true + }, + { + "url": "/portfolio/page/4/", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/portfolio/portfolio-4-test-post/", + "categories": false, + "title": "Portfolio 4 test post", + "description": "Aenean vel arcu enim. Aliquam sed rutrum erat, porta mattis lorem. Nulla scelerisque eu ligula eget dictum. Phasellus orci nisi." + }, + { + "url": "/portfolio/portfolio-3-test-post/", + "categories": false, + "title": "Portfolio 3 test post", + "description": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie." + } + ], + "pagination": [ + { + "url": "/portfolio/page/1/", + "text": "1", + "standard": true + }, + { + "url": "/portfolio/page/2/", + "text": "2", + "standard": true + }, + { + "url": "/portfolio/page/3/", + "text": "3", + "standard": true + }, + { + "text": "4", + "active": true + }, + { + "url": "/portfolio/page/5/", + "text": "5", + "standard": true + }, + { + "url": "/portfolio/page/5/", + "nextPage": true + } + ] + }, + { + "items": [ + { + "url": "/portfolio/portfolio-2-test-post/", + "categories": false, + "title": "Portfolio 2 test post", + "description": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce." + }, + { + "url": "/portfolio/portfolio-1-test-post/", + "categories": false, + "title": "Portfolio 1 test post", + "description": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat." + } + ], + "pagination": [ + { + "url": "/portfolio/page/1/", + "text": "1", + "standard": true + }, + { + "text": "…", + "dots": true + }, + { + "url": "/portfolio/page/3/", + "text": "3", + "standard": true + }, + { + "url": "/portfolio/page/4/", + "text": "4", + "standard": true + }, + { + "text": "5", + "active": true + } + ] + } +] diff --git a/tests/fixtures/archive/portfolio-posts.json b/tests/fixtures/archive/portfolio-posts.json new file mode 100644 index 00000000..cffffb78 --- /dev/null +++ b/tests/fixtures/archive/portfolio-posts.json @@ -0,0 +1,88 @@ +[ + { + "title": "Portfolio 1 test post", + "postType": "portfolio", + "content": "TMauris id tincidunt urna, ut mattis mauris. Curabitur in massa vel felis pretium aliquet vitae ut elit. Aenean at volutpat.", + "categories": ["sea", "ocean", "something"], + "tags": ["tag 1", "tag 2", "tag 3"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 2 test post", + "postType": "portfolio", + "content": "Nam at nibh feugiat, semper nisl vel, porttitor nibh. Aliquam massa diam, tincidunt nec lobortis a, fermentum vitae elit. Fusce.", + "categories": ["bicycle", "car", "something"], + "tags": ["tag 3", "tag 4", "tag 5"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 3 test post", + "postType": "portfolio", + "content": "Aliquam sed pretium purus. Cras viverra viverra felis. Ut vitae massa felis. Curabitur tempus vitae eros eu feugiat. Ut molestie.", + "categories": ["car", "ocean"], + "tags": ["tag 1", "tag 4"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 4 test post", + "postType": "portfolio", + "content": "Aenean vel arcu enim. Aliquam sed rutrum erat, porta mattis lorem. Nulla scelerisque eu ligula eget dictum. Phasellus orci nisi.", + "categories": ["car"], + "tags": ["tag 3"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 5 test post", + "postType": "portfolio", + "content": "Morbi tincidunt aliquet velit vitae imperdiet. Curabitur ex mauris, pharetra sit amet varius in, iaculis at libero. Interdum et malesuada.", + "categories": ["ocean"], + "tags": ["tag 2", "tag 3"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 6 test post", + "postType": "portfolio", + "content": "Aenean consectetur massa sed aliquet mollis. Etiam elementum lacus sed urna faucibus pulvinar. Duis dictum nisl eget urna vestibulum semper.", + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 7 test post", + "postType": "portfolio", + "content": "Nulla tincidunt arcu in dictum elementum. Quisque fringilla venenatis nulla ut sollicitudin. Praesent facilisis a libero laoreet viverra. Nunc placerat.", + "categories": ["ocean"], + "tags": ["tag 2", "tag 3"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 8 test post", + "postType": "portfolio", + "content": "Morbi id justo tortor. Morbi semper faucibus ligula, ut porttitor velit facilisis eget. Aliquam eleifend dignissim neque nec placerat. Nulla.", + "categories": ["sea"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 9 test post", + "postType": "portfolio", + "content": "Quisque tristique, velit et auctor ultrices, ante diam faucibus tellus, quis sodales leo nulla eu ante. Sed condimentum dolor gravida.", + "tags": ["tag 1"], + "showWelcomeGuide": false, + "legacyCanvas": true + }, + { + "title": "Portfolio 10 test post", + "postType": "portfolio", + "content": "Curabitur mollis convallis congue. Pellentesque vel lobortis diam. Morbi et sagittis mi, mollis vehicula dui. Maecenas arcu justo, facilisis non.", + "categories": ["pesto"], + "tags": ["tag 6"], + "showWelcomeGuide": false, + "legacyCanvas": true + } +] From cdf7bc416a33187e2026f59bc7d8d71897caa5ec Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 16:51:51 +0300 Subject: [PATCH 08/13] fixed php unit tests --- tests/phpunit/unit/test-class-friendly-urls.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/phpunit/unit/test-class-friendly-urls.php b/tests/phpunit/unit/test-class-friendly-urls.php index c0241dc9..80fe3162 100644 --- a/tests/phpunit/unit/test-class-friendly-urls.php +++ b/tests/phpunit/unit/test-class-friendly-urls.php @@ -53,6 +53,7 @@ public function get_predefined_options() { 'content_source' => 'post-based', 'posts_source' => 'current_query', ); + update_option( 'permalink_structure', '/%postname%/' ); return $block_options; } From b7dafcdcf3400c9f49acf015598eece04064a8d7 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Fri, 26 Jul 2024 17:55:34 +0300 Subject: [PATCH 09/13] added tests to check adding pictures to a block and changing their options manually and automatically (title, descriptions, etc) --- tests/e2e/specs/added-images-to-block.spec.js | 766 ++++++++++++++++++ 1 file changed, 766 insertions(+) create mode 100644 tests/e2e/specs/added-images-to-block.spec.js diff --git a/tests/e2e/specs/added-images-to-block.spec.js b/tests/e2e/specs/added-images-to-block.spec.js new file mode 100644 index 00000000..0ea39483 --- /dev/null +++ b/tests/e2e/specs/added-images-to-block.spec.js @@ -0,0 +1,766 @@ +/** + * WordPress dependencies + */ +import { expect, test } from '@wordpress/e2e-test-utils-playwright'; + +/** + * Test Images + */ +import imageFixtures from '../../fixtures/images.json'; +import { findAsyncSequential } from '../utils/find-async-sequential'; +import { getWordpressImages } from '../utils/get-wordpress-images'; + +test.describe('added images to block', () => { + test.beforeEach(async ({ requestUtils }) => { + await requestUtils.activatePlugin( + 'visual-portfolio-posts-amp-image-gallery' + ); + await requestUtils.deleteAllMedia(); + await requestUtils.deleteAllPages(); + }); + test.afterEach(async ({ requestUtils }) => { + await requestUtils.deleteAllMedia(); + await requestUtils.deleteAllPages(); + }); + + async function generateGalleryBeforeEachTest( + requestUtils, + page, + admin, + editor, + programmatically = false, + alternativeSetting = false + ) { + await admin.visitAdminPage('edit.php'); + + await admin.createNewPost({ + title: 'Test Adding Images to a Block Programmatically', + postType: 'page', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + const images = await getWordpressImages({ + requestUtils, + page, + admin, + editor, + alternativeSetting, + }); + + let attributes = { + setup_wizard: 'false', + content_source: 'images', + }; + + if (programmatically) { + attributes = { + ...attributes, + images, + }; + } + + await editor.insertBlock({ + name: 'visual-portfolio/block', + attributes, + }); + + return images; + } + + test('added images to a block manually', async ({ + page, + admin, + editor, + requestUtils, + }) => { + const images = await generateGalleryBeforeEachTest( + requestUtils, + page, + admin, + editor + ); + + await page + .locator( + 'button.components-button.vpf-component-gallery-control-item-add', + { + hasText: 'Add Images', + } + ) + .click(); + + await page + .locator('button#menu-item-browse', { + hasText: 'Media Library', + }) + .click(); + + const imageList = page.locator( + 'ul.attachments.ui-sortable.ui-sortable-disabled li.attachment[role="checkbox"]' + ); + + for (const image of await imageList.elementHandles()) { + if ( + typeof images.find( + async (x) => x.id === (await image.getAttribute('data-id')) + ).imgUrl !== 'undefined' + ) { + await image.click(); + } + } + + await page + .locator('button.button.media-button.media-button-select', { + hasText: 'Select', + }) + .click(); + + await page + .locator('.components-base-control__field', { + hasText: 'Items Per Page', + }) + .locator('input.components-text-control__input') + .fill('10'); + + await page.waitForTimeout(500); + + // Check images on backend editor. + for (const image of images) { + await expect( + page.frame('vpf-preview-1').locator('.wp-image-' + image.id) + ).toBeVisible(); + } + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + // Check images on frontend. + for (const image of images) { + await expect(page.locator('.wp-image-' + image.id)).toBeVisible(); + } + }); + + test('added images to a block programmatically', async ({ + page, + admin, + editor, + requestUtils, + }) => { + const images = await generateGalleryBeforeEachTest( + requestUtils, + page, + admin, + editor, + true + ); + + await page + .locator('.components-base-control__field', { + hasText: 'Items Per Page', + }) + .locator('input.components-text-control__input') + .fill('10'); + + await page.waitForTimeout(500); + + // Check images on backend editor. + for (const image of images) { + await expect( + page.frame('vpf-preview-1').locator('.wp-image-' + image.id) + ).toBeVisible(); + } + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + // Check images on frontend. + for (const image of images) { + await expect(page.locator('.wp-image-' + image.id)).toBeVisible(); + } + }); + + test('checking image settings', async ({ + page, + admin, + editor, + requestUtils, + }) => { + const images = await generateGalleryBeforeEachTest( + requestUtils, + page, + admin, + editor + ); + + await page + .locator( + 'button.components-button.vpf-component-gallery-control-item-add', + { + hasText: 'Add Images', + } + ) + .click(); + + await page + .locator('button#menu-item-browse', { + hasText: 'Media Library', + }) + .click(); + + const imageList = page.locator( + 'ul.attachments.ui-sortable.ui-sortable-disabled li.attachment[role="checkbox"]' + ); + + for (const image of await imageList.elementHandles()) { + if ( + typeof images.find( + async (x) => x.id === (await image.getAttribute('data-id')) + ).imgUrl !== 'undefined' + ) { + await image.click(); + + const imageID = await image.getAttribute('data-id'); + + const foundImage = await findAsyncSequential( + images, + async (x) => x.id === Number(imageID) + ); + + const foundFixture = await findAsyncSequential( + imageFixtures, + async (x) => x.description === foundImage.description + ); + + await page + .locator('#attachment-details-alt-text') + .fill(foundFixture.alt); + + await page + .locator('#attachment-details-caption') + .fill(foundFixture.caption); + + await page + .locator('#attachment-details-description') + .fill(foundFixture.description); + } + } + + await page + .locator('button.button.media-button.media-button-select', { + hasText: 'Select', + }) + .click(); + + await page + .locator('.components-base-control__field', { + hasText: 'Items Per Page', + }) + .locator('input.components-text-control__input') + .fill('10'); + + await page + .locator('button.components-button.components-panel__body-toggle', { + hasText: 'Skin', + }) + .click(); + + await page + .locator( + 'button.components-button.vpf-component-icon-selector-item', + { + hasText: 'Classic', + } + ) + .click(); + + await page + .locator('button.components-button.components-navigator-button', { + hasText: 'Caption', + }) + .click(); + + await page + .locator( + 'button.components-button.vpf-component-collapse-control-toggle', + { + hasText: 'Elements', + } + ) + .click(); + + await page.getByRole('checkbox', { name: 'Display Excerpt' }).check(); + + await page.waitForTimeout(500); + + // Check images on backend editor. + for (const image of images) { + const imageContainer = page + .frame('vpf-preview-1') + .locator('.wp-image-' + image.id); + await expect(imageContainer).toBeVisible(); + + await expect( + page + .frame('vpf-preview-1') + .locator('.vp-portfolio__item-meta-excerpt', { + hasText: image.description, + }) + ).toBeVisible(); + + const foundFixture = await findAsyncSequential( + imageFixtures, + async (x) => x.description === image.description + ); + + await expect( + page.frame('vpf-preview-1').getByAltText(foundFixture.alt) + ).toBeVisible(); + } + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + // Check images on frontend. + for (const image of images) { + await expect(page.locator('.wp-image-' + image.id)).toBeVisible(); + + const itemContainer = page + .locator('.vp-portfolio__item') + .filter({ has: page.locator('.wp-image-' + image.id) }); + + await expect(itemContainer).toBeVisible(); + + const descriptionText = itemContainer.locator( + '.vp-portfolio__item-meta-excerpt div' + ); + + await expect(descriptionText).toHaveText(image.description); + + const foundFixture = await findAsyncSequential( + imageFixtures, + async (x) => x.description === image.description + ); + + await expect(page.getByAltText(foundFixture.alt)).toBeVisible(); + } + }); + + test('checking alternative image settings', async ({ + page, + admin, + editor, + requestUtils, + }) => { + const currentPage = page.url(); + + await admin.createNewPost({ + title: 'Sample Test Page', + postType: 'page', + content: 'Test content', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + const postLink = page.url(); + + await page.goto(currentPage); + + const images = await generateGalleryBeforeEachTest( + requestUtils, + page, + admin, + editor + ); + + await page + .locator( + 'button.components-button.vpf-component-gallery-control-item-add', + { + hasText: 'Add Images', + } + ) + .click(); + + await page + .locator('button#menu-item-browse', { + hasText: 'Media Library', + }) + .click(); + + const imageList = page.locator( + 'ul.attachments.ui-sortable.ui-sortable-disabled li.attachment[role="checkbox"]' + ); + + for (const image of await imageList.elementHandles()) { + if ( + typeof images.find( + async (x) => x.id === (await image.getAttribute('data-id')) + ).imgUrl !== 'undefined' + ) { + await image.click(); + + const imageID = await image.getAttribute('data-id'); + + const foundImage = await findAsyncSequential( + images, + async (x) => x.id === Number(imageID) + ); + + const foundFixture = await findAsyncSequential( + imageFixtures, + async (x) => x.description === foundImage.description + ); + + await page + .locator('#attachment-details-alt-text') + .fill(foundFixture.alt); + + await page + .locator('#attachment-details-caption') + .fill(foundFixture.caption); + + await page + .locator('#attachment-details-description') + .fill(foundFixture.description); + } + } + + await page + .locator('button.button.media-button.media-button-select', { + hasText: 'Select', + }) + .click(); + + await page + .locator('.components-base-control__field', { + hasText: 'Items Per Page', + }) + .locator('input.components-text-control__input') + .fill('10'); + + await page + .locator('button.components-button.components-panel__body-toggle', { + hasText: 'Skin', + }) + .click(); + + await page + .locator( + 'button.components-button.vpf-component-icon-selector-item', + { + hasText: 'Classic', + } + ) + .click(); + + await page + .locator('button.components-button.components-navigator-button', { + hasText: 'Caption', + }) + .click(); + + await page + .locator( + 'button.components-button.vpf-component-collapse-control-toggle', + { + hasText: 'Elements', + } + ) + .click(); + + await page.getByRole('checkbox', { name: 'Display Excerpt' }).check(); + + const galleryControlItems = page.locator( + '.vpf-component-gallery-control-items .vpf-component-gallery-control-item' + ); + + for (const item of await galleryControlItems.elementHandles()) { + await item.click(); + + const itemDescription = await page + .locator('.components-base-control__field', { + hasText: 'Description', + }) + .locator('textarea.components-textarea-control__input') + .innerHTML(); + + const foundImage = await findAsyncSequential( + images, + async (x) => x.description === itemDescription + ); + + const foundFixture = await findAsyncSequential( + imageFixtures, + async (x) => x.description === itemDescription + ); + + const foundFixtureIndex = imageFixtures.indexOf(foundFixture); + + imageFixtures[foundFixtureIndex].id = foundImage.id; + + if (typeof foundFixture.imageSettings !== 'undefined') { + await page + .locator( + '.vpf-component-gallery-control-item-modal .components-base-control__field', + { + hasText: 'Title', + } + ) + .locator('input.components-text-control__input') + .fill(foundFixture.imageSettings.title); + + await page + .locator( + '.vpf-component-gallery-control-item-modal .components-base-control__field', + { + hasText: 'Description', + } + ) + .locator('textarea.components-textarea-control__input') + .fill(foundFixture.imageSettings.description); + + if (typeof foundFixture.imageSettings.format !== 'undefined') { + await page + .locator( + '.vpf-component-gallery-control-item-modal .components-base-control__field', + { + hasText: 'Format', + } + ) + .locator('.vpf-component-select') + .click(); + + await page + .locator('.vpf-component-select-option-label', { + hasText: foundFixture.imageSettings.format, + }) + .click(); + + if ( + foundFixture.imageSettings.format === 'standard' && + typeof foundFixture.imageSettings.url !== 'undefined' + ) { + foundFixture.imageSettings.url = + foundFixture.imageSettings.url === 'postLink' + ? postLink + : foundFixture.imageSettings.url; + + await page + .getByRole('textbox', { name: 'URL', exact: true }) + .fill(foundFixture.imageSettings.url); + } + + if ( + foundFixture.imageSettings.format === 'video' && + typeof foundFixture.imageSettings.videoUrl !== + 'undefined' + ) { + await page + .locator( + '.vpf-component-gallery-control-item-modal .components-base-control__field', + { + hasText: 'Video URL', + } + ) + .locator('input.components-text-control__input') + .fill(foundFixture.imageSettings.videoUrl); + } + } + } + + await page.getByLabel('Close', { exact: true }).click(); + } + + // Check image attributes on backend editor. + for (const image of imageFixtures) { + const imageContainer = page + .frame('vpf-preview-1') + .locator('.wp-image-' + image.id); + await expect(imageContainer).toBeVisible(); + + if (typeof image.imageSettings !== 'undefined') { + await expect( + page + .frame('vpf-preview-1') + .locator('.vp-portfolio__item-meta-excerpt', { + hasText: image.imageSettings.description, + }) + ).toBeVisible(); + + await expect( + page + .frame('vpf-preview-1') + .locator('.vp-portfolio__item-meta-title > a', { + hasText: image.imageSettings.title, + }) + ).toBeVisible(); + + if (typeof image.imageSettings.format !== 'undefined') { + const format = image.imageSettings.format; + if ( + format === 'standard' && + typeof image.imageSettings.url !== 'undefined' + ) { + await expect( + page + .frame('vpf-preview-1') + .locator('.vp-portfolio__item-meta-title > a', { + hasText: image.imageSettings.title, + }) + ).toHaveAttribute('href', image.imageSettings.url); + + await expect( + page + .frame('vpf-preview-1') + .getByRole('link', { name: image.alt }) + ).toHaveAttribute('href', image.imageSettings.url); + } + + if ( + format === 'video' && + typeof image.imageSettings.videoUrl !== 'undefined' + ) { + await expect( + page + .frame('vpf-preview-1') + .locator('.vp-portfolio__item-meta-title > a', { + hasText: image.imageSettings.title, + }) + ).toHaveAttribute('href', image.imageSettings.videoUrl); + + await expect( + page + .frame('vpf-preview-1') + .getByRole('link', { name: image.alt }) + ).toHaveAttribute('href', image.imageSettings.videoUrl); + } + } + } else { + await expect( + page + .frame('vpf-preview-1') + .locator('.vp-portfolio__item-meta-excerpt', { + hasText: image.description, + }) + ).toBeVisible(); + } + + await expect( + page.frame('vpf-preview-1').getByAltText(image.alt) + ).toBeVisible(); + } + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + // Check image attributes on frontend. + for (const image of imageFixtures) { + await expect(page.locator('.wp-image-' + image.id)).toBeVisible(); + + const itemContainer = page + .locator('.vp-portfolio__item') + .filter({ has: page.locator('.wp-image-' + image.id) }); + + await expect(itemContainer).toBeVisible(); + + if (typeof image.imageSettings !== 'undefined') { + await expect( + page.locator('.vp-portfolio__item-meta-excerpt', { + hasText: image.imageSettings.description, + }) + ).toBeVisible(); + + await expect( + page.locator('.vp-portfolio__item-meta-title > a', { + hasText: image.imageSettings.title, + }) + ).toBeVisible(); + + if (typeof image.imageSettings.format !== 'undefined') { + const format = image.imageSettings.format; + if ( + format === 'standard' && + typeof image.imageSettings.url !== 'undefined' + ) { + await expect( + page.locator('.vp-portfolio__item-meta-title > a', { + hasText: image.imageSettings.title, + }) + ).toHaveAttribute('href', image.imageSettings.url); + + await expect( + page.getByRole('link', { name: image.alt }) + ).toHaveAttribute('href', image.imageSettings.url); + } + + if ( + format === 'video' && + typeof image.imageSettings.videoUrl !== 'undefined' + ) { + await expect( + page.locator('.vp-portfolio__item-meta-title > a', { + hasText: image.imageSettings.title, + }) + ).toHaveAttribute('href', image.imageSettings.videoUrl); + + await expect( + page.getByRole('link', { name: image.alt }) + ).toHaveAttribute('href', image.imageSettings.videoUrl); + } + } + } else { + await expect( + page.locator('.vp-portfolio__item-meta-excerpt', { + hasText: image.description, + }) + ).toBeVisible(); + } + + await expect(page.getByAltText(image.alt)).toBeVisible(); + } + }); +}); From ace8e4839e5d04fdfa83958c76fb8f9a98878932 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Tue, 30 Jul 2024 12:55:06 +0300 Subject: [PATCH 10/13] added tests for checking free click actions (disabled, url, popup) --- tests/e2e/specs/click-action-images.spec.js | 459 ++++++++++++++++++ .../click-actions/popup-expected-preset.json | 72 +++ .../click-actions/url-expected-preset.json | 52 ++ 3 files changed, 583 insertions(+) create mode 100644 tests/e2e/specs/click-action-images.spec.js create mode 100644 tests/fixtures/click-actions/popup-expected-preset.json create mode 100644 tests/fixtures/click-actions/url-expected-preset.json diff --git a/tests/e2e/specs/click-action-images.spec.js b/tests/e2e/specs/click-action-images.spec.js new file mode 100644 index 00000000..635ca5c6 --- /dev/null +++ b/tests/e2e/specs/click-action-images.spec.js @@ -0,0 +1,459 @@ +/** + * WordPress dependencies + */ +import { expect, test } from '@wordpress/e2e-test-utils-playwright'; + +import expectedPopupPreset from '../../fixtures/click-actions/popup-expected-preset.json'; +import expectedUrlPreset from '../../fixtures/click-actions/url-expected-preset.json'; +import { findAsyncSequential } from '../utils/find-async-sequential'; +import { getWordpressImages } from '../utils/get-wordpress-images'; + +test.describe('click action gallery images', () => { + test.beforeAll(async ({ requestUtils }) => { + await requestUtils.activatePlugin( + 'visual-portfolio-posts-amp-image-gallery' + ); + await requestUtils.deleteAllMedia(); + await requestUtils.deleteAllPages(); + }); + test.afterAll(async ({ requestUtils }) => { + await requestUtils.deleteAllMedia(); + await requestUtils.deleteAllPages(); + }); + + test('check disabled click action', async ({ + page, + admin, + editor, + requestUtils, + }) => { + await admin.createNewPost({ + title: 'Click Action', + postType: 'page', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + const images = await getWordpressImages({ + requestUtils, + page, + admin, + editor, + }); + + await editor.insertBlock({ + name: 'visual-portfolio/block', + attributes: { + setup_wizard: 'false', + content_source: 'images', + }, + }); + + await page + .locator( + 'button.components-button.vpf-component-gallery-control-item-add', + { + hasText: 'Add Images', + } + ) + .click(); + + await page + .locator('button#menu-item-browse', { + hasText: 'Media Library', + }) + .click(); + + const imageList = page.locator( + 'ul.attachments.ui-sortable.ui-sortable-disabled li.attachment[role="checkbox"]' + ); + + for (const image of await imageList.elementHandles()) { + if ( + typeof images.find( + async (x) => x.id === (await image.getAttribute('data-id')) + ).imgUrl !== 'undefined' + ) { + await image.click(); + } + } + + await page + .locator('button.button.media-button.media-button-select', { + hasText: 'Select', + }) + .click(); + + await page + .locator('.components-panel__body', { + hasText: 'Click Action', + }) + .click(); + + await page + .locator( + 'button.components-button.vpf-component-icon-selector-item', + { + hasText: 'Disabled', + } + ) + .click(); + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + const link = page.locator('a.vp-portfolio__item-meta'); + + await expect(link).toBeHidden(); + }); + + test('check url click action', async ({ + page, + admin, + editor, + requestUtils, + }) => { + // Create post for testing click action. + await admin.createNewPost({ + title: 'URL Click Action', + postType: 'page', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + // Get images for test gallery. + const images = await getWordpressImages({ + requestUtils, + page, + admin, + editor, + alternativeSetting: true, + }); + + /** + * Prepare the fixture. + * Change the date in the link to the image to the current one. + * Also insert the test domain used at the beginning of the link + */ + const testBaseUrl = process.env.PLAYWRIGHT_TEST_BASE_URL; + + const today = new Date(); + + let month = Number(today.getMonth() + 1); + + if (month < 10) { + month = '0' + month; + } + + const currentYearAndMonth = today.getFullYear() + '/' + month; + + expectedUrlPreset.map(async (object, key) => { + if (object.titleUrl.includes('/wp-content/')) { + const titleUrl = testBaseUrl + object.titleUrl; + expectedUrlPreset[key].titleUrl = titleUrl.replace( + /0000\/00/i, + currentYearAndMonth + ); + } + + if (object.titleUrl.includes('page_id')) { + const foundImage = await findAsyncSequential( + images, + async (x) => x.title === object.title + ); + + expectedUrlPreset[key].titleUrl = foundImage.url; + } + }); + + await editor.insertBlock({ + name: 'visual-portfolio/block', + attributes: { + setup_wizard: 'false', + content_source: 'images', + items_style: 'default', + images, + items_click_action: 'url', + }, + }); + + await page + .locator('.components-base-control__field', { + hasText: 'Items Per Page', + }) + .locator('input.components-text-control__input') + .fill('10'); + + await page.waitForTimeout(2000); + + const galleryImages = page + .frame('vpf-preview-1') + .locator('.vp-portfolio__items .vp-portfolio__item-wrap'); + + const receivedUrlBackendPreset = []; + + // Check Backend. + for (const galleryImage of await galleryImages.all()) { + /** + * Check the layout and collect an array with information about items. + */ + const popup = await galleryImage + .locator('.vp-portfolio__item-popup') + .count(); + const title = galleryImage.locator( + '.vp-portfolio__item-meta-title > a' + ); + const titleText = await title.innerText(); + const titleUrl = await title.getAttribute('href'); + const isPopup = popup ? true : false; + + receivedUrlBackendPreset.push({ + title: titleText, + isPopup, + titleUrl, + }); + } + + // Compare the Backend resulting array of objects with the expected one. + expect(receivedUrlBackendPreset).toEqual(expectedUrlPreset); + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + // Check Frontend. + const galleryFrontendImages = page.locator( + '.vp-portfolio__items .vp-portfolio__item-wrap' + ); + + const receivedUrlFrontendPreset = []; + + for (const galleryImage of await galleryFrontendImages.all()) { + const popup = await galleryImage + .locator('.vp-portfolio__item-popup') + .count(); + const title = galleryImage.locator( + '.vp-portfolio__item-meta-title > a' + ); + const titleText = await title.innerText(); + const titleUrl = await title.getAttribute('href'); + const isPopup = popup ? true : false; + + receivedUrlFrontendPreset.push({ + title: titleText, + isPopup, + titleUrl, + }); + } + + // Compare the Frontend resulting array of objects with the expected one. + expect(receivedUrlFrontendPreset).toEqual(expectedUrlPreset); + }); + + test('check popup click action', async ({ + page, + admin, + editor, + requestUtils, + }) => { + // Create post for testing click action. + await admin.createNewPost({ + title: 'URL Click Action', + postType: 'page', + showWelcomeGuide: false, + legacyCanvas: true, + }); + + // Get images for test gallery. + const images = await getWordpressImages({ + requestUtils, + page, + admin, + editor, + alternativeSetting: true, + }); + + /** + * Prepare the fixture. + * Change the date in the link to the image to the current one. + * Also insert the test domain used at the beginning of the link + */ + const testBaseUrl = process.env.PLAYWRIGHT_TEST_BASE_URL; + + const today = new Date(); + + let month = Number(today.getMonth() + 1); + + if (month < 10) { + month = '0' + month; + } + + const currentYearAndMonth = today.getFullYear() + '/' + month; + + expectedPopupPreset.map(async (object, key) => { + if (object.titleUrl.includes('/wp-content/')) { + const titleUrl = testBaseUrl + object.titleUrl; + expectedPopupPreset[key].titleUrl = titleUrl.replace( + /0000\/00/i, + currentYearAndMonth + ); + } + + if (object.imageUrl && object.imageUrl.includes('/wp-content/')) { + const imageUrl = testBaseUrl + object.imageUrl; + expectedPopupPreset[key].imageUrl = imageUrl.replace( + /0000\/00/i, + currentYearAndMonth + ); + } + + if (object.titleUrl.includes('page_id')) { + const foundImage = await findAsyncSequential( + images, + async (x) => x.title === object.title + ); + + expectedPopupPreset[key].titleUrl = foundImage.url; + } + }); + + await editor.insertBlock({ + name: 'visual-portfolio/block', + attributes: { + setup_wizard: 'false', + content_source: 'images', + items_style: 'default', + images, + items_click_action: 'popup_gallery', + }, + }); + + await page + .locator('.components-base-control__field', { + hasText: 'Items Per Page', + }) + .locator('input.components-text-control__input') + .fill('10'); + + await page.waitForTimeout(3000); + + const galleryImages = page + .frame('vpf-preview-1') + .locator('.vp-portfolio__items .vp-portfolio__item-wrap'); + + const receivedPopupBackendPreset = []; + + // Check Backend. + for (const galleryImage of await galleryImages.all()) { + /** + * Check the layout and collect an array with information about items. + */ + const popup = galleryImage.locator('.vp-portfolio__item-popup'); + const isVideoPopup = await galleryImage + .locator('[data-vp-popup-video]') + .count(); + const isImagePopup = await galleryImage + .locator('[data-vp-popup-img]') + .count(); + const title = galleryImage.locator( + '.vp-portfolio__item-meta-title > a' + ); + const titleText = await title.innerText(); + const titleUrl = await title.getAttribute('href'); + const isPopup = (await popup.count()) ? true : false; + + let videoUrl = false, + imageUrl = false; + + if (isVideoPopup) { + videoUrl = await popup.getAttribute('data-vp-popup-video'); + } + + if (isImagePopup) { + imageUrl = await popup.getAttribute('data-vp-popup-img'); + } + + receivedPopupBackendPreset.push({ + title: titleText, + isPopup, + titleUrl, + imageUrl, + videoUrl, + }); + } + + // Compare the Backend resulting array of objects with the expected one. + expect(receivedPopupBackendPreset).toEqual(expectedPopupPreset); + + // Publish Post. + await editor.publishPost(); + + // Go to published post. + await page + .locator('.components-button', { + hasText: 'View Page', + }) + .first() + .click(); + + // Check Frontend. + const galleryFrontendImages = page.locator( + '.vp-portfolio__items .vp-portfolio__item-wrap' + ); + + const receivedPopupFrontendPreset = []; + + for (const galleryImage of await galleryFrontendImages.all()) { + const popup = galleryImage.locator('.vp-portfolio__item-popup'); + const isVideoPopup = await galleryImage + .locator('[data-vp-popup-video]') + .count(); + const isImagePopup = await galleryImage + .locator('[data-vp-popup-img]') + .count(); + const title = galleryImage.locator( + '.vp-portfolio__item-meta-title > a' + ); + const titleText = await title.innerText(); + const titleUrl = await title.getAttribute('href'); + const isPopup = (await popup.count()) ? true : false; + + let videoUrl = false, + imageUrl = false; + + if (isVideoPopup) { + videoUrl = await popup.getAttribute('data-vp-popup-video'); + } + + if (isImagePopup) { + imageUrl = await popup.getAttribute('data-vp-popup-img'); + } + + receivedPopupFrontendPreset.push({ + title: titleText, + isPopup, + titleUrl, + imageUrl, + videoUrl, + }); + } + + // Compare the Frontend resulting array of objects with the expected one. + expect(receivedPopupFrontendPreset).toEqual(expectedPopupPreset); + }); +}); diff --git a/tests/fixtures/click-actions/popup-expected-preset.json b/tests/fixtures/click-actions/popup-expected-preset.json new file mode 100644 index 00000000..96ee382f --- /dev/null +++ b/tests/fixtures/click-actions/popup-expected-preset.json @@ -0,0 +1,72 @@ +[ + { + "title": "Alternative title of 300 on 200", + "isPopup": true, + "titleUrl": "https://www.youtube.com/watch?v=354pybu91aQ&ab_channel=VisualPortfolio", + "imageUrl": false, + "videoUrl": "https://www.youtube.com/watch?v=354pybu91aQ&ab_channel=VisualPortfolio" + }, + { + "title": "Alternative title of 600 on 1920", + "isPopup": false, + "titleUrl": "https://visualportfolio.co/", + "imageUrl": false, + "videoUrl": false + }, + { + "title": "Alternative title of 800 on 600", + "isPopup": true, + "titleUrl": "/wp-content/uploads/0000/00/image-800x600-2.png", + "imageUrl": "/wp-content/uploads/0000/00/image-800x600-2.png", + "videoUrl": false + }, + { + "title": "Alternative title of 800 on 1200", + "isPopup": false, + "titleUrl": "/?page_id=3534", + "imageUrl": false, + "videoUrl": false + }, + { + "title": "Alternative title of 1600 on 1200", + "isPopup": true, + "titleUrl": "/wp-content/uploads/0000/00/image-1600x1200-2.jpeg", + "imageUrl": "/wp-content/uploads/0000/00/image-1600x1200-2.jpeg", + "videoUrl": false + }, + { + "title": "Alternative title of 1920 on 600", + "isPopup": true, + "titleUrl": "https://www.youtube.com/watch?v=354pybu91aQ&ab_channel=VisualPortfolio", + "imageUrl": false, + "videoUrl": "https://www.youtube.com/watch?v=354pybu91aQ&ab_channel=VisualPortfolio" + }, + { + "title": "Image Title of 1920 on 1080", + "isPopup": true, + "titleUrl": "/wp-content/uploads/0000/00/image-1920x1080-2.jpeg", + "imageUrl": "/wp-content/uploads/0000/00/image-1920x1080-2.jpeg", + "videoUrl": false + }, + { + "title": "Image Title of 2000 on 2000", + "isPopup": true, + "titleUrl": "/wp-content/uploads/0000/00/image-2000x2000-2-1920x1920.jpeg", + "imageUrl": "/wp-content/uploads/0000/00/image-2000x2000-2-1920x1920.jpeg", + "videoUrl": false + }, + { + "title": "Image Title of 3840 on 2160", + "isPopup": true, + "titleUrl": "/wp-content/uploads/0000/00/image-3840x2160-2-1920x1080.jpeg", + "imageUrl": "/wp-content/uploads/0000/00/image-3840x2160-2-1920x1080.jpeg", + "videoUrl": false + }, + { + "title": "Image Title of 3840 on 2560", + "isPopup": true, + "titleUrl": "/wp-content/uploads/0000/00/image-3840x2560-2-1920x1280.jpeg", + "imageUrl": "/wp-content/uploads/0000/00/image-3840x2560-2-1920x1280.jpeg", + "videoUrl": false + } + ] diff --git a/tests/fixtures/click-actions/url-expected-preset.json b/tests/fixtures/click-actions/url-expected-preset.json new file mode 100644 index 00000000..da55b481 --- /dev/null +++ b/tests/fixtures/click-actions/url-expected-preset.json @@ -0,0 +1,52 @@ +[ + { + "title": "Alternative title of 300 on 200", + "isPopup": false, + "titleUrl": "https://www.youtube.com/watch?v=354pybu91aQ&ab_channel=VisualPortfolio" + }, + { + "title": "Alternative title of 600 on 1920", + "isPopup": false, + "titleUrl": "https://visualportfolio.co/" + }, + { + "title": "Alternative title of 800 on 600", + "isPopup": false, + "titleUrl": "/wp-content/uploads/0000/00/image-800x600-2.png" + }, + { + "title": "Alternative title of 800 on 1200", + "isPopup": false, + "titleUrl": "/?page_id" + }, + { + "title": "Alternative title of 1600 on 1200", + "isPopup": false, + "titleUrl": "/wp-content/uploads/0000/00/image-1600x1200-2.jpeg" + }, + { + "title": "Alternative title of 1920 on 600", + "isPopup": false, + "titleUrl": "https://www.youtube.com/watch?v=354pybu91aQ&ab_channel=VisualPortfolio" + }, + { + "title": "Image Title of 1920 on 1080", + "isPopup": false, + "titleUrl": "/wp-content/uploads/0000/00/image-1920x1080-2.jpeg" + }, + { + "title": "Image Title of 2000 on 2000", + "isPopup": false, + "titleUrl": "/wp-content/uploads/0000/00/image-2000x2000-2-1920x1920.jpeg" + }, + { + "title": "Image Title of 3840 on 2160", + "isPopup": false, + "titleUrl": "/wp-content/uploads/0000/00/image-3840x2160-2-1920x1080.jpeg" + }, + { + "title": "Image Title of 3840 on 2560", + "isPopup": false, + "titleUrl": "/wp-content/uploads/0000/00/image-3840x2560-2-1920x1280.jpeg" + } +] From 9481d10671d31c5758fd02acd399e05082d7364d Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Tue, 30 Jul 2024 15:59:08 +0300 Subject: [PATCH 11/13] fixed fixtures for click action tests and added functions for prepare this fixtures --- tests/e2e/specs/click-action-images.spec.js | 95 +++++++++++++++++++ .../click-actions/popup-expected-preset.json | 2 +- .../click-actions/url-expected-preset.json | 12 +-- 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/tests/e2e/specs/click-action-images.spec.js b/tests/e2e/specs/click-action-images.spec.js index 635ca5c6..939ac572 100644 --- a/tests/e2e/specs/click-action-images.spec.js +++ b/tests/e2e/specs/click-action-images.spec.js @@ -21,6 +21,56 @@ test.describe('click action gallery images', () => { await requestUtils.deleteAllPages(); }); + async function preparePopupFixture(size, property, key) { + if ( + typeof expectedPopupPreset[key][property] === 'string' && + expectedPopupPreset[key][property].includes(size) + ) { + switch (size) { + case '2000x2000': + expectedPopupPreset[key][property] = expectedPopupPreset[ + key + ][property].replace('.jpeg', '-1920x1920.jpeg'); + break; + case '3840x2160': + expectedPopupPreset[key][property] = expectedPopupPreset[ + key + ][property].replace('scaled.jpeg', '1920x1080.jpeg'); + break; + case '3840x2560': + expectedPopupPreset[key][property] = expectedPopupPreset[ + key + ][property].replace('scaled.jpeg', '1920x1280.jpeg'); + break; + } + } + } + + async function prepareUrlFixture(size, property, key) { + if ( + typeof expectedUrlPreset[key][property] === 'string' && + expectedUrlPreset[key][property].includes(size) + ) { + switch (size) { + case '2000x2000': + expectedUrlPreset[key][property] = expectedUrlPreset[key][ + property + ].replace('.jpeg', '-1920x1920.jpeg'); + break; + case '3840x2160': + expectedUrlPreset[key][property] = expectedUrlPreset[key][ + property + ].replace('scaled.jpeg', '1920x1080.jpeg'); + break; + case '3840x2560': + expectedUrlPreset[key][property] = expectedUrlPreset[key][ + property + ].replace('scaled.jpeg', '1920x1280.jpeg'); + break; + } + } + } + test('check disabled click action', async ({ page, admin, @@ -172,6 +222,22 @@ test.describe('click action gallery images', () => { expectedUrlPreset[key].titleUrl = foundImage.url; } + + if (object.titleUrl.includes('image')) { + const foundImage = await findAsyncSequential( + images, + async (x) => x.title === object.title + ); + + expectedUrlPreset[key].titleUrl = foundImage.imgUrl; + + const match = foundImage.imgUrl.match(/(\d+x\d+)/); + + if (match) { + const size = match[0]; + await prepareUrlFixture(size, 'titleUrl', key); + } + } }); await editor.insertBlock({ @@ -330,6 +396,35 @@ test.describe('click action gallery images', () => { expectedPopupPreset[key].titleUrl = foundImage.url; } + + if (object.titleUrl.includes('image')) { + const foundImage = await findAsyncSequential( + images, + async (x) => x.title === object.title + ); + + expectedPopupPreset[key].titleUrl = foundImage.imgUrl; + } + + if ( + typeof object.imageUrl === 'string' && + object.imageUrl.includes('image') + ) { + const foundImage = await findAsyncSequential( + images, + async (x) => x.title === object.title + ); + + expectedPopupPreset[key].imageUrl = foundImage.imgUrl; + + const match = foundImage.imgUrl.match(/(\d+x\d+)/); + + if (match) { + const size = match[0]; + await preparePopupFixture(size, 'titleUrl', key); + await preparePopupFixture(size, 'imageUrl', key); + } + } }); await editor.insertBlock({ diff --git a/tests/fixtures/click-actions/popup-expected-preset.json b/tests/fixtures/click-actions/popup-expected-preset.json index 96ee382f..03e8ae5c 100644 --- a/tests/fixtures/click-actions/popup-expected-preset.json +++ b/tests/fixtures/click-actions/popup-expected-preset.json @@ -69,4 +69,4 @@ "imageUrl": "/wp-content/uploads/0000/00/image-3840x2560-2-1920x1280.jpeg", "videoUrl": false } - ] +] diff --git a/tests/fixtures/click-actions/url-expected-preset.json b/tests/fixtures/click-actions/url-expected-preset.json index da55b481..01ed43ef 100644 --- a/tests/fixtures/click-actions/url-expected-preset.json +++ b/tests/fixtures/click-actions/url-expected-preset.json @@ -12,7 +12,7 @@ { "title": "Alternative title of 800 on 600", "isPopup": false, - "titleUrl": "/wp-content/uploads/0000/00/image-800x600-2.png" + "titleUrl": "/wp-content/uploads/0000/00/image-800x600-1.png" }, { "title": "Alternative title of 800 on 1200", @@ -22,7 +22,7 @@ { "title": "Alternative title of 1600 on 1200", "isPopup": false, - "titleUrl": "/wp-content/uploads/0000/00/image-1600x1200-2.jpeg" + "titleUrl": "/wp-content/uploads/0000/00/image-1600x1200-1.jpeg" }, { "title": "Alternative title of 1920 on 600", @@ -32,21 +32,21 @@ { "title": "Image Title of 1920 on 1080", "isPopup": false, - "titleUrl": "/wp-content/uploads/0000/00/image-1920x1080-2.jpeg" + "titleUrl": "/wp-content/uploads/0000/00/image-1920x1080-1.jpeg" }, { "title": "Image Title of 2000 on 2000", "isPopup": false, - "titleUrl": "/wp-content/uploads/0000/00/image-2000x2000-2-1920x1920.jpeg" + "titleUrl": "/wp-content/uploads/0000/00/image-2000x2000-1-1920x1920.jpeg" }, { "title": "Image Title of 3840 on 2160", "isPopup": false, - "titleUrl": "/wp-content/uploads/0000/00/image-3840x2160-2-1920x1080.jpeg" + "titleUrl": "/wp-content/uploads/0000/00/image-3840x2160-1-1920x1080.jpeg" }, { "title": "Image Title of 3840 on 2560", "isPopup": false, - "titleUrl": "/wp-content/uploads/0000/00/image-3840x2560-2-1920x1280.jpeg" + "titleUrl": "/wp-content/uploads/0000/00/image-3840x2560-1-1920x1280.jpeg" } ] From 0e16a57270115f8a25f258a13343b6402c507ce7 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Tue, 30 Jul 2024 20:01:35 +0300 Subject: [PATCH 12/13] added support for running core tests in the pro version --- tests/e2e/specs/added-images-to-block.spec.js | 7 ++++--- tests/e2e/specs/archive.spec.js | 7 ++++--- tests/e2e/specs/click-action-images.spec.js | 7 ++++--- tests/e2e/specs/initial-loading.spec.js | 7 ++++--- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/tests/e2e/specs/added-images-to-block.spec.js b/tests/e2e/specs/added-images-to-block.spec.js index 0ea39483..521cae6a 100644 --- a/tests/e2e/specs/added-images-to-block.spec.js +++ b/tests/e2e/specs/added-images-to-block.spec.js @@ -12,9 +12,10 @@ import { getWordpressImages } from '../utils/get-wordpress-images'; test.describe('added images to block', () => { test.beforeEach(async ({ requestUtils }) => { - await requestUtils.activatePlugin( - 'visual-portfolio-posts-amp-image-gallery' - ); + const pluginName = process.env.CORE + ? 'visual-portfolio-pro' + : 'visual-portfolio-posts-amp-image-gallery'; + await requestUtils.activatePlugin(pluginName); await requestUtils.deleteAllMedia(); await requestUtils.deleteAllPages(); }); diff --git a/tests/e2e/specs/archive.spec.js b/tests/e2e/specs/archive.spec.js index 17db8d1f..5ec6ed4c 100644 --- a/tests/e2e/specs/archive.spec.js +++ b/tests/e2e/specs/archive.spec.js @@ -15,9 +15,10 @@ import { getWordpressImages } from '../utils/get-wordpress-images'; test.describe('archive pages', () => { test.beforeEach(async ({ requestUtils }) => { - await requestUtils.activatePlugin( - 'visual-portfolio-posts-amp-image-gallery' - ); + const pluginName = process.env.CORE + ? 'visual-portfolio-pro' + : 'visual-portfolio-posts-amp-image-gallery'; + await requestUtils.activatePlugin(pluginName); await requestUtils.deleteAllMedia(); await requestUtils.deleteAllPages(); await requestUtils.deleteAllPosts(); diff --git a/tests/e2e/specs/click-action-images.spec.js b/tests/e2e/specs/click-action-images.spec.js index 939ac572..b612c5a2 100644 --- a/tests/e2e/specs/click-action-images.spec.js +++ b/tests/e2e/specs/click-action-images.spec.js @@ -10,9 +10,10 @@ import { getWordpressImages } from '../utils/get-wordpress-images'; test.describe('click action gallery images', () => { test.beforeAll(async ({ requestUtils }) => { - await requestUtils.activatePlugin( - 'visual-portfolio-posts-amp-image-gallery' - ); + const pluginName = process.env.CORE + ? 'visual-portfolio-pro' + : 'visual-portfolio-posts-amp-image-gallery'; + await requestUtils.activatePlugin(pluginName); await requestUtils.deleteAllMedia(); await requestUtils.deleteAllPages(); }); diff --git a/tests/e2e/specs/initial-loading.spec.js b/tests/e2e/specs/initial-loading.spec.js index 3077b959..ab6b255c 100644 --- a/tests/e2e/specs/initial-loading.spec.js +++ b/tests/e2e/specs/initial-loading.spec.js @@ -2,9 +2,10 @@ import { expect, test } from '@wordpress/e2e-test-utils-playwright'; test.describe('initial loading', () => { test.beforeAll(async ({ requestUtils }) => { - await requestUtils.activatePlugin( - 'visual-portfolio-posts-amp-image-gallery' - ); + const pluginName = process.env.CORE + ? 'visual-portfolio-pro' + : 'visual-portfolio-posts-amp-image-gallery'; + await requestUtils.activatePlugin(pluginName); }); test('should have visual portfolio in admin menu', async ({ From a24e338df9c517d48b05b8ffe2d533291e4a0281 Mon Sep 17 00:00:00 2001 From: Fellan-91 Date: Thu, 1 Aug 2024 19:50:07 +0300 Subject: [PATCH 13/13] Added comments for testing functions --- tests/e2e/specs/added-images-to-block.spec.js | 11 +++ tests/e2e/specs/archive.spec.js | 87 +++++++++++++++++++ tests/e2e/specs/click-action-images.spec.js | 16 ++++ tests/e2e/utils/get-wordpress-images.js | 13 +++ 4 files changed, 127 insertions(+) diff --git a/tests/e2e/specs/added-images-to-block.spec.js b/tests/e2e/specs/added-images-to-block.spec.js index 521cae6a..1882e5fa 100644 --- a/tests/e2e/specs/added-images-to-block.spec.js +++ b/tests/e2e/specs/added-images-to-block.spec.js @@ -24,6 +24,17 @@ test.describe('added images to block', () => { await requestUtils.deleteAllPages(); }); + /** + * We create a gallery block and add pictures to it manually or automatically. + * + * @param {RequestUtils} requestUtils Playwright utilities for interacting with the WordPress REST API. + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Editor} editor End to end test utilities for the WordPress Block Editor. + * @param {boolean} programmatically Flag for setting manual or automatic adding of pictures to the block. + * @param {boolean} alternativeSetting Flag for setting alternative meta settings for test images. + * @return {{images: {format: string, video_url: string, url: string}[]}} + */ async function generateGalleryBeforeEachTest( requestUtils, page, diff --git a/tests/e2e/specs/archive.spec.js b/tests/e2e/specs/archive.spec.js index 5ec6ed4c..7ed9b724 100644 --- a/tests/e2e/specs/archive.spec.js +++ b/tests/e2e/specs/archive.spec.js @@ -31,6 +31,12 @@ test.describe('archive pages', () => { await deleteAllPortfolio({ requestUtils }); }); + /** + * Deleting all categories of portfolio posts. + * + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + */ async function deletePortfolioCategories(admin, page) { await admin.visitAdminPage( 'edit-tags.php?taxonomy=portfolio_category&post_type=portfolio' @@ -45,6 +51,12 @@ test.describe('archive pages', () => { } } + /** + * Deleting all tags of portfolio posts. + * + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + */ async function deletePortfolioTags(admin, page) { await admin.visitAdminPage( 'edit-tags.php?taxonomy=portfolio_tag&post_type=portfolio' @@ -59,6 +71,11 @@ test.describe('archive pages', () => { } } + /** + * We get all archive items from the archive page on the front end within the current pagination or selected category. + * + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + */ async function getArchiveItems(page) { const archiveItems = []; const items = page.locator( @@ -113,6 +130,16 @@ test.describe('archive pages', () => { return archiveItems; } + /** + * We create portfolio posts for the archives page. + * We fill these posts with pictures, titles, descriptions and other necessary meta data. + * We also set tags and categories. + * + * @param {RequestUtils} requestUtils Playwright utilities for interacting with the WordPress REST API. + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Editor} editor End to end test utilities for the WordPress Block Editor. + */ async function createPortfolioPosts(requestUtils, page, admin, editor) { const images = await getWordpressImages({ requestUtils, @@ -242,6 +269,16 @@ test.describe('archive pages', () => { } } + /** + * We create an archives page and place a block with archive settings on it. + * We select the number of elements displayed on the page, skin and pagination display. + * Setting the display of the category filter. + * + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Editor} editor End to end test utilities for the WordPress Block Editor. + * @return {{archiveID: number, archiveUrl: string}} Return object with archive page ID and archive URL. + */ async function createArchivePage(page, admin, editor) { await admin.createNewPost({ title: 'Portfolio', @@ -301,6 +338,12 @@ test.describe('archive pages', () => { }; } + /** + * Install the previously created archives page in the plugin settings. + * + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + */ async function setArchiveSettings(admin, page) { await admin.visitAdminPage('edit.php?post_type=portfolio'); @@ -314,6 +357,41 @@ test.describe('archive pages', () => { await page.getByRole('button', { name: 'Save Changes' }).click(); } + /** + * We receive an array of objects with archive elements in the process of querying the layout on the front-end side. + * This array will be used as a comparison array against the expected result. + * During the survey process, we also collect information about the current state of pagination, + * Understanding what page we are on and what elements surround us. + * + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @return { + * { + * items: + * { + * url: any, categories: any, title: any, description: any + * }[], + * pagination: ( + * { + * text: any, + * active: boolean + * } | + * { + * url: any, + * text: any, + * standard: boolean + * } | + * { + * text: any, + * dots: boolean + * } | + * { + * url: any, + * nextPage: boolean + * } + * )[] + * } + * []} + */ async function getReceivedArchive(page) { const pageCounts = 5; const receivedArchive = []; @@ -407,6 +485,15 @@ test.describe('archive pages', () => { return receivedArchive; } + /** + * We receive an array of objects with category elements in the process of querying the layout on the front-end side. + * This array will be used as a comparison array against the expected result. + * During the survey process, we also collect information about the current state of pagination, + * Understanding what page we are on and what elements surround us. + * + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @return {{title: any, url: any, items: never[]}[]} + */ async function getReceivedCategories(page) { const filterItems = page .locator('.vp-filter .vp-filter__item') diff --git a/tests/e2e/specs/click-action-images.spec.js b/tests/e2e/specs/click-action-images.spec.js index b612c5a2..ae2d7905 100644 --- a/tests/e2e/specs/click-action-images.spec.js +++ b/tests/e2e/specs/click-action-images.spec.js @@ -22,6 +22,14 @@ test.describe('click action gallery images', () => { await requestUtils.deleteAllPages(); }); + /** + * We prepare the fixture for popup comparison. + * We correct the paths to the images to be current, loaded into the WordPress system. + * + * @param {string} size Image Resolution. + * @param {string} property Image property. + * @param {number} key Key of Image object. + */ async function preparePopupFixture(size, property, key) { if ( typeof expectedPopupPreset[key][property] === 'string' && @@ -47,6 +55,14 @@ test.describe('click action gallery images', () => { } } + /** + * We prepare the fixture for url comparison. + * We correct the paths to the images to be current, loaded into the WordPress system. + * + * @param {string} size Image Resolution. + * @param {string} property Image property. + * @param {number} key Key of Image object. + */ async function prepareUrlFixture(size, property, key) { if ( typeof expectedUrlPreset[key][property] === 'string' && diff --git a/tests/e2e/utils/get-wordpress-images.js b/tests/e2e/utils/get-wordpress-images.js index e4bd39a1..1a66c4ef 100644 --- a/tests/e2e/utils/get-wordpress-images.js +++ b/tests/e2e/utils/get-wordpress-images.js @@ -8,6 +8,15 @@ const path = require('path'); */ import imagePaths from '../../fixtures/images.json'; +/** + * + * @param {RequestUtils} requestUtils Playwright utilities for interacting with the WordPress REST API. + * @param {Page} page Provides methods to interact with a single tab in a Browser, or an extension background page in Chromium. + * @param {Admin} admin End to end test utilities for WordPress admin’s user interface. + * @param {Editor} editor End to end test utilities for the WordPress Block Editor. + * @param {boolean} alternativeSetting Set alternative meta settings for test images. + * @return {{images: {format: string, video_url: string, url: string}[]}} + */ export async function getWordpressImages({ requestUtils, page, @@ -21,6 +30,7 @@ export async function getWordpressImages({ if (alternativeSetting) { const currentPage = page.url(); + // Create a post for a image that has a link to an internal WordPress post. await admin.createNewPost({ title: 'Sample Test Page', postType: 'page', @@ -40,6 +50,7 @@ export async function getWordpressImages({ .first() .click(); + // Remember the link to the post for future use inside the meta image. postLink = page.url(); await page.goto(currentPage); @@ -48,12 +59,14 @@ export async function getWordpressImages({ images = await Promise.all( imagePaths.map(async (object) => { const filepath = path.join('tests/fixtures/', object.filename); + // Upload image to WordPress gallery. const media = await requestUtils.uploadMedia(filepath); const periodIndex = object.filename.indexOf('.'); let image = {}; + // We collect all the meta data of the image and write it to an array. let title = periodIndex !== -1 ? object.filename.substring(0, periodIndex)