From 40629b05ce29ae2fb5aee50916f26ba2fcb1407e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 14:45:19 +0200 Subject: [PATCH 01/11] Revise instructions for UI screenshot validation Updated UI validation instructions for clarity and detail. --- AIVision/library.py | 57 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 6 deletions(-) diff --git a/AIVision/library.py b/AIVision/library.py index bf77317..753d158 100644 --- a/AIVision/library.py +++ b/AIVision/library.py @@ -162,12 +162,57 @@ def verify_screenshot_matches_look_and_feel_template(self, screenshot_path, temp except Exception as e: logger.warn(f"Could not create combined image: {e}") - instructions = """First image is showing actual application view. -Second image is reference design template. -Verify screenshot matches look and feel template. Pay attention to details, design is important. -Make sure to check also all the visible logos, titles, labels, spelling, texts, links, menus, banners -and any available graphics. Always doublecheck the reference image in case you think some -text, label, logo or element is overlapping or containing typo. + instructions = """ +First image is the actual application screenshot. +Second image is the reference design/template screenshot. + +Compare the actual screenshot against the reference screenshot as a visual UI/template validation. + +Primary goal: +Verify that the actual page matches the reference page in layout, visual structure, branding, and look-and-feel. + +Check carefully: +- Overall page structure and visual hierarchy +- Header, navigation, menu icons, logos, brand marks, and banners +- Sections, cards, panels, containers, borders, backgrounds, shadows, and spacing +- Buttons, links, icons, badges, dropdowns, input fields, and other interactive elements +- Element positions, alignment, relative sizing, padding, margins, and grouping +- Font style, font weight, approximate font size, text alignment, and color usage +- Overlapping, clipped, truncated, hidden, misplaced, or visually broken elements +- Unexpected wrapping, excessive spacing, missing spacing, or layout shifts +- Whether all expected visible UI elements are present + +Important text comparison rules: +Do not compare dynamic text values literally. Values such as phone numbers, account numbers, names, balances, prices, dates, times, counts, statuses, identifiers, and user-specific data may be different and must not cause failure. + +Treat dynamic text as visual text blocks: +- The exact value may differ. +- The text block should still appear in the expected location. +- It should have similar styling, size, alignment, color, and visual weight. +- It should not break the layout, overlap other elements, be clipped, or cause unexpected wrapping. + +Static/template text rules: +Static labels, headings, menu names, fixed links, fixed button labels, fixed section names, and fixed instructional texts should be checked only when they are clearly part of the template. +However, do not fail only because the actual text content differs if the difference appears to be dynamic or user-specific. + +Ignore: +- Browser chrome, OS status bars, emulator/device frames, address bars, scroll bars, timestamps, debug overlays, and comparison labels such as "Actual" or "Expected", unless they are part of the application UI. +- Minor anti-aliasing differences, screenshot compression artifacts, tiny pixel-level shifts, and insignificant rendering differences. +- Small differences caused by platform/browser font rendering if the layout and visual hierarchy remain correct. + +Fail the comparison when: +- A required UI element is missing or an unexpected major UI element is present. +- Logo, header, menu, navigation, main section, card, button, link, or icon is visually incorrect or misplaced. +- Layout structure differs significantly from the reference. +- Elements overlap, are clipped, truncated, hidden, or visually broken. +- Text blocks are present but their placement, style, size, color, or wrapping materially differs from the reference. +- Spacing, alignment, sizing, or visual hierarchy is noticeably inconsistent with the reference. +- The page looks like a different template, broken responsive layout, or incorrect design version. + +Pass the comparison when: +- The actual screenshot preserves the same layout, structure, visual hierarchy, branding, and front-end appearance as the reference. +- Differences are limited to dynamic text values or insignificant rendering variations. +- All expected elements are present and visually usable. """ if override_instructions: instructions = override_instructions From 790bff0f54d9c2bea88c4e27173b4397ef24a21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 14:46:22 +0200 Subject: [PATCH 02/11] Add version 1.3.0 release notes to CHANGES.txt --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index 8bd5535..f36f017 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,4 @@ +1.3.0, 2026-05-25 -- Look and Feel layout comparison assertion strategy improved and made more robust 1.2.0, 2026-02-24 -- Image size optimizations, additional_instructions can now be passed to look and feel check keyword 1.1.2, 2026-02-09 -- Improved debug logging 1.1.1, 2026-02-09 -- Pass/Fail AI response optimized From f8fe108b0e7ed3e36ed2244083fdc7e751a34a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 14:54:24 +0200 Subject: [PATCH 03/11] Add project URLs to setup.py --- setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/setup.py b/setup.py index 4c0eb9a..2d4cf39 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,12 @@ def readme(): long_description=readme(), long_description_content_type='text/markdown', url='https://github.com/robco/robotframework-aivision.git', + project_urls={ + "Homepage": "https://robo-corp.malovec.sk", + "Repository": "https://github.com/robco/robotframework-aivision", + "Documentation": "https://robco.github.io/robotframework-aivision/", + "Issues": "https://github.com/robco/robotframework-aivision/issues", + }, author='RĂ³bert Malovec', author_email='robert@malovec.sk', license=license(), From 221664e08290ca098f243ad6de4275bb6510a430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 14:59:35 +0200 Subject: [PATCH 04/11] Update assertions in test_library.py for accuracy --- unittests/test_library.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/test_library.py b/unittests/test_library.py index ebf3af4..be527e7 100644 --- a/unittests/test_library.py +++ b/unittests/test_library.py @@ -213,8 +213,8 @@ def test_verify_screenshot_matches_look_and_feel_template_with_additional_instru mock_genai.generate_ai_response.assert_called_once() instructions = mock_genai.generate_ai_response.call_args[1]["instructions"] - assert "First image is showing actual application view" in instructions - assert instructions.endswith("Ignore clock in header.") + assert "First image is showing actual application screenshot" in instructions + assert instructions.endswith("All expected elements are present and visually usable.") assert mock_genai.generate_ai_response.call_args[1]["image_paths"] == [ "/path/to/screenshot.png", "/path/to/template.png", From 0709f734d3321bc21c441714b0547bfee02e6a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:10:10 +0200 Subject: [PATCH 05/11] Add coverage for AIVision in pytest command --- .github/workflows/python-package.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index d8b0f3e..356ac04 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -130,7 +130,7 @@ jobs: # Run tests with multiple output formats python -m pytest unittests/ \ - --cov=epg_grabber \ + --cov=AIVision \ --cov-report=xml \ --cov-report=html \ --cov-report=term-missing \ From 2273f5131145f7999f6a911973165fc2157fd4ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:14:09 +0200 Subject: [PATCH 06/11] Update assertion message in test for AI response --- unittests/test_library.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_library.py b/unittests/test_library.py index be527e7..73c85a1 100644 --- a/unittests/test_library.py +++ b/unittests/test_library.py @@ -183,7 +183,7 @@ def test_verify_screenshot_matches_look_and_feel_template(self, library, mock_ge ) mock_genai.generate_ai_response.assert_called_once() - assert "First image is showing actual application view" in mock_genai.generate_ai_response.call_args[1][ + assert "First image is showing actual application screenshot" in mock_genai.generate_ai_response.call_args[1][ 'instructions'] assert mock_genai.generate_ai_response.call_args[1]['image_paths'] == ["/path/to/screenshot.png", "/path/to/template.png"] From db4d92805c3a4b057e26ea7027cb18ccd59e43b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:15:36 +0200 Subject: [PATCH 07/11] Update assertions in test_lib.py for accuracy --- unittests/test_lib.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/test_lib.py b/unittests/test_lib.py index d527894..cc150aa 100644 --- a/unittests/test_lib.py +++ b/unittests/test_lib.py @@ -62,8 +62,8 @@ def test_verify_screenshot_matches_look_and_feel_template_with_additional_instru additional_instructions="Ignore status badge." ) instructions = aivison_library.genai.generate_ai_response.call_args[1]["instructions"] - assert "First image is showing actual application view" in instructions - assert instructions.endswith("Ignore status badge.") + assert "First image is showing actual application screenshot" in instructions + assert instructions.endswith("All expected elements are present and visually usable.") aivison_library._assert_result.assert_called_once_with("response") From fd7efff1d94f3926cf107fea2b5eda2b37551555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:17:32 +0200 Subject: [PATCH 08/11] Update test_lib.py --- unittests/test_lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_lib.py b/unittests/test_lib.py index cc150aa..668fcb5 100644 --- a/unittests/test_lib.py +++ b/unittests/test_lib.py @@ -62,7 +62,7 @@ def test_verify_screenshot_matches_look_and_feel_template_with_additional_instru additional_instructions="Ignore status badge." ) instructions = aivison_library.genai.generate_ai_response.call_args[1]["instructions"] - assert "First image is showing actual application screenshot" in instructions + assert "First image is the actual application screenshot" in instructions assert instructions.endswith("All expected elements are present and visually usable.") aivison_library._assert_result.assert_called_once_with("response") From 50ee307af5959732450353ba10359ce8e27e8b6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:18:06 +0200 Subject: [PATCH 09/11] Fix assertion message in test_library.py --- unittests/test_library.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unittests/test_library.py b/unittests/test_library.py index 73c85a1..2349ec5 100644 --- a/unittests/test_library.py +++ b/unittests/test_library.py @@ -183,7 +183,7 @@ def test_verify_screenshot_matches_look_and_feel_template(self, library, mock_ge ) mock_genai.generate_ai_response.assert_called_once() - assert "First image is showing actual application screenshot" in mock_genai.generate_ai_response.call_args[1][ + assert "First image is the actual application screenshot" in mock_genai.generate_ai_response.call_args[1][ 'instructions'] assert mock_genai.generate_ai_response.call_args[1]['image_paths'] == ["/path/to/screenshot.png", "/path/to/template.png"] @@ -213,7 +213,7 @@ def test_verify_screenshot_matches_look_and_feel_template_with_additional_instru mock_genai.generate_ai_response.assert_called_once() instructions = mock_genai.generate_ai_response.call_args[1]["instructions"] - assert "First image is showing actual application screenshot" in instructions + assert "First image is the actual application screenshot" in instructions assert instructions.endswith("All expected elements are present and visually usable.") assert mock_genai.generate_ai_response.call_args[1]["image_paths"] == [ "/path/to/screenshot.png", From e8842d9f7209568fe06b84fdfebeed0937b6af8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:21:39 +0200 Subject: [PATCH 10/11] Update assertion for instructions in test_library.py --- unittests/test_library.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_library.py b/unittests/test_library.py index 2349ec5..f7d3165 100644 --- a/unittests/test_library.py +++ b/unittests/test_library.py @@ -214,7 +214,7 @@ def test_verify_screenshot_matches_look_and_feel_template_with_additional_instru mock_genai.generate_ai_response.assert_called_once() instructions = mock_genai.generate_ai_response.call_args[1]["instructions"] assert "First image is the actual application screenshot" in instructions - assert instructions.endswith("All expected elements are present and visually usable.") + assert instructions.endswith("Ignore clock in header.") assert mock_genai.generate_ai_response.call_args[1]["image_paths"] == [ "/path/to/screenshot.png", "/path/to/template.png", From ed959eafbd3deb45c2eedd6e9fc0c8a706888d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Malovec?= Date: Mon, 25 May 2026 15:22:10 +0200 Subject: [PATCH 11/11] Update assertion for instructions in test_lib.py --- unittests/test_lib.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittests/test_lib.py b/unittests/test_lib.py index 668fcb5..c836e51 100644 --- a/unittests/test_lib.py +++ b/unittests/test_lib.py @@ -63,7 +63,7 @@ def test_verify_screenshot_matches_look_and_feel_template_with_additional_instru ) instructions = aivison_library.genai.generate_ai_response.call_args[1]["instructions"] assert "First image is the actual application screenshot" in instructions - assert instructions.endswith("All expected elements are present and visually usable.") + assert instructions.endswith("Ignore status badge.") aivison_library._assert_result.assert_called_once_with("response")