From 2a62b3c4b6bd39438ca7e56ee30922d2d6aab98a Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Thu, 10 Oct 2024 12:10:06 +0800 Subject: [PATCH 01/35] chore: add Oobee brand colours and fonts to root --- src/static/ejs/partials/styles/styles.ejs | 45 +++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/static/ejs/partials/styles/styles.ejs b/src/static/ejs/partials/styles/styles.ejs index ac7ea43e..e0723e2e 100644 --- a/src/static/ejs/partials/styles/styles.ejs +++ b/src/static/ejs/partials/styles/styles.ejs @@ -97,6 +97,45 @@ --needs-review-icon: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M17.1429 0H2.85714C1.27919 0 0 1.27919 0 2.85714V17.1429C0 18.7208 1.27919 20 2.85714 20H17.1429C18.7208 20 20 18.7208 20 17.1429V2.85714C20 1.27919 18.7208 0 17.1429 0Z' fill='%236A8A95'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.09759 7.26594C8.23445 6.67496 8.46462 6.23328 8.7881 5.9409C9.14891 5.65474 9.57815 5.51166 10.0758 5.51166C10.5984 5.51166 11.0152 5.64852 11.3262 5.92224C11.6372 6.19596 11.7928 6.53188 11.7928 6.93002C11.7928 7.22862 11.7057 7.48367 11.5315 7.69518C11.4195 7.84448 11.0712 8.15552 10.4864 8.6283C9.90785 9.11353 9.51594 9.54277 9.31065 9.91602C9.12403 10.3079 9.03072 10.7745 9.03072 11.3157V11.7449L9.04938 11.8569C9.04938 11.9316 9.06026 12 9.08204 12.0622C9.10381 12.1244 9.12558 12.1742 9.14736 12.2115C9.16913 12.2488 9.20645 12.2815 9.25933 12.3095C9.31221 12.3375 9.35264 12.3593 9.38064 12.3748C9.40863 12.3904 9.45995 12.4012 9.5346 12.4075C9.60925 12.4137 9.66058 12.4168 9.68857 12.4168H9.85187H10.0012C10.2065 12.4168 10.3589 12.409 10.4584 12.3935C10.5579 12.3779 10.6466 12.3313 10.7243 12.2535C10.8021 12.1757 10.841 12.056 10.841 11.8942C10.841 11.6827 10.8534 11.465 10.8783 11.2411C10.897 11.0109 10.9343 10.8305 10.9903 10.6998C11.0712 10.5008 11.3324 10.2208 11.7741 9.86003C12.6077 9.15707 13.1427 8.61587 13.3791 8.23639C13.6279 7.83204 13.7523 7.41524 13.7523 6.986C13.7523 6.17729 13.4102 5.48678 12.7259 4.91446C12.0603 4.30482 11.1458 4 9.9825 4C8.88763 4 8.00428 4.2986 7.33243 4.8958C6.71656 5.41835 6.36198 6.07154 6.26866 6.85537C6.25622 6.89269 6.25 6.9549 6.25 7.04199C6.25 7.29705 6.3402 7.51633 6.52061 7.69984C6.70101 7.88336 6.91563 7.97512 7.16446 7.97512C7.37597 7.97512 7.56571 7.90824 7.73367 7.77449C7.90163 7.64075 8.0105 7.47123 8.06026 7.26594H8.09759ZM10.0012 13.2939C9.62791 13.2939 9.30754 13.4246 9.04005 13.6858C8.77255 13.9471 8.6388 14.2644 8.6388 14.6376C8.6388 15.0047 8.77255 15.3235 9.04005 15.5941C9.30754 15.8647 9.62791 16 10.0012 16C10.3744 16 10.6948 15.8647 10.9623 15.5941C11.2298 15.3235 11.3635 15.0047 11.3635 14.6376C11.3635 14.2644 11.2298 13.9471 10.9623 13.6858C10.6948 13.4246 10.3744 13.2939 10.0012 13.2939Z' fill='white'/%3E%3C/svg%3E%0A"); --passed-icon: url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M17.1429 0H2.85714C1.27919 0 0 1.27919 0 2.85714V17.1429C0 18.7208 1.27919 20 2.85714 20H17.1429C18.7208 20 20 18.7208 20 17.1429V2.85714C20 1.27919 18.7208 0 17.1429 0Z' fill='%23039855'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M15.1781 5.3131C15.7942 5.80597 15.8941 6.70496 15.4012 7.32105L9.68694 14.4639C9.19407 15.08 8.29508 15.1799 7.67899 14.687C7.0629 14.1941 6.96301 13.2951 7.45589 12.6791L13.1702 5.5362C13.663 4.92011 14.562 4.82023 15.1781 5.3131Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M4.70415 9.70455C5.26204 9.14666 6.16656 9.14666 6.72446 9.70455L9.5816 12.5617C10.1395 13.1196 10.1395 14.0241 9.5816 14.582C9.02371 15.1399 8.11919 15.1399 7.56129 14.582L4.70415 11.7249C4.14626 11.167 4.14626 10.2624 4.70415 9.70455Z' fill='white'/%3E%3C/svg%3E%0A"); + + /* Oobee Brand Colours and Fonts */ + --a11y-purple-50: #f8d6ff; + --a11y-purple-70: #e5a6f2; + --a11y-purple-100-light: #9021a6; /* Primary Purple Light Mode */ + --a11y-purple-100-dark: #d54dff; /* Primary Purple Dark Mode */ + --a11y-purple-150: #642272; + --a11y-purple-highlight: #c000e5; + + /* Accents - RGBY */ + --coral-red-50: #ffb7a6; + --coral-red-70: #f27961; + --coral-red-100: #f26949; + --coral-red-150: #a53419; + --leaf-green-50: #ace5c3; + --leaf-green-70: #5cc487; + --leaf-green-100: #3aa566; + --leaf-green-150: #146635; + --sky-blue-50: #9ee0f2; + --sky-blue-70: #73d5e5; + --sky-blue-100: #2bafd8; + --sky-blue-150: #006b8c; + --sunshine-yellow-50: #ffdfa6; + --sunshine-yellow-70: #ffd066; + --sunshine-yellow-100: #ffb200; + --sunshine-yellow-150: #a56600; + + /* Neutral Colours */ + --true-white: #ffffff; + --a11y-black-5: #f4f4f4; + --a11y-black-15: #dededd; + --a11y-black-25: #c9c8c6; + --a11y-black-50: #93928d; + --a11y-black-80: #525048; + --a11y-black-90: #3c3a32; + --a11y-black-100: #26241b; + + /* Fonts */ + --a11y-regular-paragraph: 'PT Sans'; } * { @@ -534,7 +573,8 @@ width: 100%; } - #pagesScannedModalToggle, #pagesScannedModalToggleTxt { + #pagesScannedModalToggle, + #pagesScannedModalToggleTxt { background-color: transparent; color: #0047fa; border: none; @@ -1045,8 +1085,7 @@ background-color: #7f56d9; } - .conformance-bubble.wcag22aa - { + .conformance-bubble.wcag22aa { background-color: #7f56d9; } From 6cf1de37e01cc1c00a073b6861a4640e3d7b5764 Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:47:27 +0800 Subject: [PATCH 02/35] chore: update colours --- src/static/ejs/partials/styles/styles.ejs | 128 +++++++++++----------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/src/static/ejs/partials/styles/styles.ejs b/src/static/ejs/partials/styles/styles.ejs index e0723e2e..e425baa7 100644 --- a/src/static/ejs/partials/styles/styles.ejs +++ b/src/static/ejs/partials/styles/styles.ejs @@ -4,7 +4,7 @@ /* Bootstrap CSS overrides */ #accessibility-site-report:root { - --bs-border-color: #b5c5ca; + --bs-border-color: var(--a11y-black-25); --bs-border-radius: 0.25rem; } @@ -29,14 +29,14 @@ #accessibility-site-report html { all: unset; font-family: 'Open Sans', 'Helvetica', sans-serif; - background-color: #f6f8f9; + background-color: var(--a11y-black-5); margin: 0; min-height: 100vh; line-height: 1.75rem; } #accessibility-site-report hr { - border-color: #b5c5ca; + border-color: var(--a11y-black-25); opacity: 1; } @@ -60,7 +60,7 @@ font-weight: 700; font-size: 2rem; margin-top: 0; - color: #333333; + color: var(--a11y-black-100); line-height: 2.5rem; } @@ -79,7 +79,7 @@ } #accessibility-site-report a { - color: #0047fa; + color: var(--sky-blue-150); text-decoration: none; } @@ -139,7 +139,7 @@ } * { - color: #333; + color: var(--a11y-black-100); } a[target='_blank']:after { @@ -154,7 +154,7 @@ padding: 1.5rem 1rem; display: flex; align-items: center; - border-bottom: 1px solid #b5c5ca; + border-bottom: 1px solid var(--a11y-black-25); box-shadow: 0 3px 5px 0 #736ccb1a; } @@ -186,7 +186,7 @@ .search-warning { background: rgb(229, 237, 255); - border: 1px solid var(--A11Y-Grey-400, #648fff); + border: 1px solid var(#648fff); margin-bottom: 2rem; text-align: center; } @@ -214,8 +214,8 @@ flex-wrap: nowrap; height: 76px; border-radius: 0px 0px 4px 4px; - border: 1px solid var(--A11Y-Grey-400, #b5c5ca); - background: var(--A11Y-Grey-100, #f6f8f9); + border: 1px solid var(--a11y-black-25); + background: var(--a11y-black-5); max-width: 100%; min-width: 100%; border-top: 0; @@ -227,8 +227,8 @@ height: 44px; gap: 10px; border-radius: 5px; - border: 1px solid var(--A11Y-Grey-400, #b5c5ca); - background: #f6f8f9; + border: 1px solid var(--a11y-black-25); + background: var(--a11y-black-5); box-sizing: border-box; text-align: center; justify-content: center; @@ -243,8 +243,8 @@ height: 44px; gap: 10px; border-radius: 4px; - border: 1px solid var(--A11Y-Grey-400, #b5c5ca); - background: #f6f8f9; + border: 1px solid var(--a11y-black-25); + background: var(--a11y-black-5); box-sizing: border-box; text-align: center; justify-content: center; @@ -260,8 +260,8 @@ height: 44px; gap: 10px; border-radius: 4px; - border: 1px solid var(--A11Y-Grey-400, #b5c5ca); - background: #f6f8f9; + border: 1px solid var(--a11y-black-25); + background: var(--a11y-black-5); box-sizing: border-box; text-align: center; justify-content: center; @@ -277,18 +277,18 @@ } .filter-options-group input[type='radio']:checked + label { - border: 2px solid var(--A11Y-Primary-Blue-600, #0047fa); + border: 2px solid var(--A11Y-Primary-Blue-600, var(--sky-blue-150)); background: #fff; - color: #0047fa; + color: var(--sky-blue-150); } .filter-words:hover { background: #f2f6ff; - border: 1px solid #0047fa; + border: 1px solid var(--sky-blue-150); } .filter-words { - color: #333333; + color: var(--a11y-black-100); font-size: 16px; font-family: 'Open Sans', sans-serif; font-weight: 400; @@ -335,7 +335,7 @@ position: absolute; left: -50px; font-size: 18px; - color: #0047fa; + color: var(--sky-blue-150); } .toggle:after { @@ -343,7 +343,7 @@ position: absolute; right: -48px; font-size: 18px; - color: #333333; + color: var(--a11y-black-100); } .toggle__handler { @@ -461,7 +461,7 @@ } input:checked + .toggle:before { - color: #333333; + color: var(--a11y-black-100); } input:checked + .toggle:after { @@ -576,7 +576,7 @@ #pagesScannedModalToggle, #pagesScannedModalToggleTxt { background-color: transparent; - color: #0047fa; + color: var(--sky-blue-150); border: none; padding: 0; text-align: left; @@ -607,7 +607,7 @@ display: flex; flex-direction: column; padding: 0.5rem; - border-bottom: 1px solid #b5c5ca; + border-bottom: 1px solid var(--a11y-black-25); } #pagesScannedModal .nav-tabs { border-width: 2px !important; @@ -618,18 +618,18 @@ margin-bottom: -1px; } #pagesScannedModal .nav-link.active { - border-bottom: 2px solid #0047fa; + border-bottom: 2px solid var(--sky-blue-150); } #pagesScannedModal .nav-link { border: none; - color: #333333; + color: var(--a11y-black-100); display: flex; align-items: center; gap: 0.5rem; } #pagesScannedModal .badge { background-color: #e7ecee; - color: #333333; + color: var(--a11y-black-100); text-align: center; border-radius: 8px; padding: 0.25rem 0.5rem; @@ -637,7 +637,7 @@ line-height: 1rem; } #pagesScannedModal .nav-link.active > .badge { - background-color: #0047fa; + background-color: var(--sky-blue-150); color: white; } #pagesScannedModal .not-scanned-url { @@ -678,13 +678,13 @@ #scanabout-compliance-card { box-shadow: none; border-width: 1.5px; - border-color: #b5c5ca; + border-color: var(--a11y-black-25); } .wcag-compliance-passes-panel { margin: 1.5rem 0; padding: 1rem; - border: 1px solid #b5c5ca; + border: 1px solid var(--a11y-black-25); border-radius: 0.25rem; } @@ -698,7 +698,7 @@ } #wcag-compliance-passes-bar-progress { - background-color: #785ef0; + background-color: var(--a11y-purple-100-light); position: absolute; left: 0; height: 100%; @@ -706,7 +706,7 @@ } .wcag-compliance-passes-bar-progress { - background-color: #785ef0; + background-color: var(--a11y-purple-100-light); position: absolute; left: 0; height: 100%; @@ -735,7 +735,7 @@ border: 0; padding: 0; float: right; - color: #0047fa; + color: var(--sky-blue-150); } button#wcagModalToggle:hover { @@ -803,13 +803,13 @@ } #top-five-card li:not(:last-of-type) { - border-bottom: 1px solid #b5c5ca; + border-bottom: 1px solid var(--a11y-black-25); padding-bottom: 0.5rem; margin-bottom: 0.5rem; } .category-selector { - border: 1px solid #b5c5ca; + border: 1px solid var(--a11y-black-25); background-color: white; border-radius: 0.25rem; padding: 1rem; @@ -820,7 +820,7 @@ } .category-selector.selected { - border: 2px solid #0047fa; + border: 2px solid var(--sky-blue-150); padding: calc(1rem - 1px); cursor: default; } @@ -828,7 +828,7 @@ .category-selector:not(.selected):hover { cursor: pointer; background-color: #f2f6ff; - border: 1px solid #0047fa; + border: 1px solid var(--sky-blue-150); } .category-selector .category-name { @@ -848,7 +848,7 @@ } .category-selector.selected .category-name { - color: #0047fa; + color: var(--sky-blue-150); } .category-selector.mustFix .category-name::before { @@ -916,7 +916,7 @@ width: 300px; padding: 1.5rem 1rem; word-break: break-all; - border-right: 1px solid #b5c5ca; + border-right: 1px solid var(--a11y-black-25); } #scan-about ul { @@ -978,7 +978,7 @@ width: 100%; background-color: transparent; border: 0; - border-bottom: 1px solid #b5c5ca; + border-bottom: 1px solid var(--a11y-black-25); } .rule-item:hover { @@ -1054,8 +1054,8 @@ } #expandedRule .offcanvas-body { - background-color: #f6f8f9; - border-top: 1px solid #b5c5ca; + background-color: var(--a11y-black-5); + border-top: 1px solid var(--a11y-black-25); padding: 2rem 1.5rem; overflow-y: unset; } @@ -1160,7 +1160,7 @@ #expandedRuleCategoryContent .accordion-button .counter { padding: 0.5rem; min-width: 61px; - border: 1px solid #b5c5ca; + border: 1px solid var(--a11y-black-25); border-radius: 0.375rem; padding: 0.25rem 0.5rem; font-weight: bold; @@ -1207,7 +1207,7 @@ #expandedRuleCategoryContent .accordion-body .card .needsReview { color: #4a6168; - background-color: #f6f8f9; + background-color: var(--a11y-black-5); border-bottom: 1px solid #d1dbde; padding: 0.5rem 1rem; display: flex; @@ -1243,7 +1243,7 @@ .ai-response-card { padding: 1rem; - border: 1px solid #b5c5ca; + border: 1px solid var(--a11y-black-25); background-color: #f7f6fe; border-radius: 4px; } @@ -1307,8 +1307,8 @@ #expandedRuleCategoryContent .accordion-body pre, .bg-grey-w-border { - background-color: #f6f8f9; - border: 1px solid #b5c5ca; + background-color: var(--a11y-black-5); + border: 1px solid var(--a11y-black-25); font-size: 1rem; padding: 0.5rem; white-space: normal; @@ -1347,17 +1347,17 @@ } #expandedRuleCategoryContent .page-items-count { - border: 1px solid #b5c5ca; + border: 1px solid var(--a11y-black-25); border-radius: 0.475rem; margin-left: 0.5rem; padding: 0 0.5rem; } #summary-table-header { - border-bottom: 3px solid #785ef0 !important; - border-top: 1px solid #b5c5ca; - border-left: 1px solid #b5c5ca; - border-right: 1px solid #b5c5ca; + border-bottom: 3px solid var(--a11y-purple-100-light) !important; + border-top: 1px solid var(--a11y-black-25); + border-left: 1px solid var(--a11y-black-25); + border-right: 1px solid var(--a11y-black-25); border-style: solid; padding-left: 16px; padding-top: 14px; @@ -1455,8 +1455,8 @@ } .aiGenerateResponseButton:disabled { - border: 1px solid #b5c5ca; - color: #b5c5ca; + border: 1px solid var(--a11y-black-25); + color: var(--a11y-black-25); } .aiGenerateResponseButton:hover:not(:disabled) { @@ -1517,8 +1517,8 @@ .codeForAiResponse { display: inline-block; - background-color: #f6f8f9; - border: 1px solid #b5c5ca; + background-color: var(--a11y-black-5); + border: 1px solid var(--a11y-black-25); font-size: 1rem; padding: 0.5rem; white-space: normal; @@ -1530,7 +1530,7 @@ #expandedRuleAiFeedback { margin-top: 2rem; background-color: #f7f6fe; - border: 1px solid #785ef0; + border: 1px solid var(--a11y-purple-100-light); border-radius: 4px; padding: 1rem; } @@ -1655,8 +1655,8 @@ background-color: rgb(255, 255, 255); &[aria-selected='true']::after { - border-bottom: 1px solid #333; - border-right: 1px solid #333; + border-bottom: 1px solid var(--a11y-black-100); + border-right: 1px solid var(--a11y-black-100); content: ''; height: 16px; position: absolute; @@ -1667,12 +1667,12 @@ } &:hover { - border-color: #b5c5ca; + border-color: var(--a11y-black-25); background-color: #f2f6ff; } &:focus { - border-color: #b5c5ca; + border-color: var(--a11y-black-25); background-color: #f2f6ff; } } @@ -1703,8 +1703,8 @@ .expanded-rule-issue-type-combobox-button::after, .ally-toggle-button-2::after { - border-bottom: 1px solid #333; - border-right: 1px solid #333; + border-bottom: 1px solid var(--a11y-black-100); + border-right: 1px solid var(--a11y-black-100); content: ''; display: block; height: 12px; From 7ffe63d2069c2f290fba83f37ea4904483e83210 Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Thu, 10 Oct 2024 13:52:49 +0800 Subject: [PATCH 03/35] chore: add and update font --- src/static/ejs/partials/styles/styles.ejs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/static/ejs/partials/styles/styles.ejs b/src/static/ejs/partials/styles/styles.ejs index e425baa7..3ea45f58 100644 --- a/src/static/ejs/partials/styles/styles.ejs +++ b/src/static/ejs/partials/styles/styles.ejs @@ -1,6 +1,8 @@ diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index fd72d58a..33ea9c0d 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -154,7 +154,7 @@ 'd', 'M11.9528 2.05329C9.22079 -0.68205 4.78867 -0.68477 2.0533 2.04718C-0.682042 4.7792 -0.684795 9.21135 2.04722 11.9467C4.77917 14.6821 9.21135 14.6848 11.9467 11.9528C14.682 9.22085 14.6848 4.78863 11.9528 2.05329ZM7.00216 11.2406C6.6319 11.2406 6.33174 10.9405 6.33174 10.5702C6.33174 10.1999 6.63187 9.89976 7.00216 9.89976C7.37243 9.89976 7.67259 10.1999 7.67259 10.5702C7.67255 10.9405 7.37243 11.2406 7.00216 11.2406ZM8.09214 7.20401C7.70918 7.42788 7.67645 7.7033 7.6748 8.49691C7.6747 8.54938 7.67453 8.60233 7.67423 8.65558C7.67185 9.03068 7.36712 9.33312 6.99253 9.33312C6.99105 9.33312 6.98957 9.33312 6.98813 9.33312C6.61159 9.33074 6.3083 9.02356 6.31066 8.64699C6.31099 8.59568 6.31109 8.54468 6.31119 8.49415C6.31287 7.67852 6.31492 6.66352 7.40395 6.02694C8.27777 5.51613 8.3879 5.18059 8.28543 4.74029C8.16503 4.2231 7.69273 4.08907 7.32418 4.1312C7.20042 4.14541 6.58322 4.24724 6.58322 4.85783C6.58322 5.23431 6.27795 5.5396 5.90141 5.5396C5.52487 5.5396 5.21964 5.23431 5.21964 4.85783C5.21964 3.76416 6.02107 2.90831 7.16859 2.77656C8.35043 2.64099 9.35515 3.32135 9.61338 4.4312C9.99939 6.08915 8.61379 6.89911 8.09214 7.20401Z', ); - path.setAttribute('fill', '#B5C5CA'); + path.setAttribute('fill', '#c9c8c6'); clipPath.appendChild(rect); svgIcon.appendChild(clipPath); From f69768b12aa5dfce8cd28eddac51d828b5398438 Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Thu, 10 Oct 2024 14:55:51 +0800 Subject: [PATCH 09/35] chore: prettier --- .../ejs/partials/components/reportSearch.ejs | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/static/ejs/partials/components/reportSearch.ejs b/src/static/ejs/partials/components/reportSearch.ejs index a3115026..456ac38a 100644 --- a/src/static/ejs/partials/components/reportSearch.ejs +++ b/src/static/ejs/partials/components/reportSearch.ejs @@ -1,9 +1,15 @@ -
${voteString} Useful - + Not useful @@ -388,7 +388,7 @@ document.getElementById(accordionDiv).getElementsByClassName('ai-response-card')[0].appendChild(feedbackButtonsElem); } } - + document.querySelectorAll('.codeForAiResponse').forEach(el => { hljs.highlightElement(el); }); diff --git a/src/static/ejs/partials/styles/styles.ejs b/src/static/ejs/partials/styles/styles.ejs index 88f1351b..0b293360 100644 --- a/src/static/ejs/partials/styles/styles.ejs +++ b/src/static/ejs/partials/styles/styles.ejs @@ -1237,7 +1237,7 @@ #expandedRuleCategoryContent .accordion-body .card .needsReview { color: var(--a11y-black-100); background-color: var(--a11y-black-5); - border-bottom: 1px solid #d1dbde; + border-bottom: 1px solid var(--a11y-black-25); padding: 0.5rem 1rem; display: flex; align-items: center; @@ -1273,7 +1273,7 @@ .ai-response-card { padding: 1rem; border: 1px solid var(--a11y-black-25); - background-color: #f7f6fe; + background-color: rgba(144, 33, 166, 0.05); border-radius: 4px; } @@ -1476,8 +1476,8 @@ } .aiGenerateResponseButton { - border: 1px solid #6e52ef; - color: #6e52ef; + border: 1px solid var(--a11y-purple-100-light); + color: var(--a11y-purple-100-light); background-color: var(--true-white); border-radius: 4px; padding: 0.5rem 1rem; @@ -1489,15 +1489,15 @@ } .aiGenerateResponseButton:hover:not(:disabled) { - background-color: #ebe8fd; - color: #5b3bed; - border-color: #5b3bed; + background-color: var(--a11y-purple-50); + color: var(--a11y-purple-100-light); + border-color: var(--a11y-purple-100-light); } .aiGenerateResponseButton:active:not(:disabled) { - background-color: #c0b4f8; - color: #472bc4; - border-color: #472bc4; + background-color: var(--a11y-purple-70); + color: var(--a11y-purple-150); + border-color: var(--a11y-purple-150); } .generateAiError { @@ -1509,7 +1509,7 @@ color: var(--a11y-black-100); } - .undoAiFeedback { + .undoAiFeedback:hover { text-decoration: underline !important; } @@ -1521,8 +1521,8 @@ .aiFeedbackButton { background-color: var(--true-white); - border: 1px solid #6e52ef; - color: #6e52ef; + border: 1px solid var(--a11y-purple-100-light); + color: var(--a11y-purple-100-light); border-radius: 4px; padding: 0.25rem 1rem; font-size: 0.875rem; @@ -1533,15 +1533,15 @@ } .aiFeedbackButton:hover { - background-color: #ebe8fd; - color: #5b3bed; - border-color: #5b3bed; + background-color: var(--a11y-purple-50); + color: var(--a11y-purple-100-light); + border-color: var(--a11y-purple-100-light); } .aiFeedbackButton:active { - background-color: #c0b4f8; - color: #472bc4; - border-color: #472bc4; + background-color: var(--a11y-purple-70); + color: var(--a11y-purple-150); + border-color: var(--a11y-purple-150); } .codeForAiResponse { @@ -1558,7 +1558,7 @@ #expandedRuleAiFeedback { margin-top: 2rem; - background-color: #f7f6fe; + background-color: rgba(144, 33, 166, 0.05); border: 1px solid var(--a11y-purple-100-light); border-radius: 4px; padding: 1rem; From 58c5657e7456242a57c756550a35ff3ba6b6d687 Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:20:13 +0800 Subject: [PATCH 26/35] chore: add spacing to header --- src/static/ejs/partials/styles/styles.ejs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/static/ejs/partials/styles/styles.ejs b/src/static/ejs/partials/styles/styles.ejs index 0b293360..701bef81 100644 --- a/src/static/ejs/partials/styles/styles.ejs +++ b/src/static/ejs/partials/styles/styles.ejs @@ -175,6 +175,7 @@ align-items: center; border-bottom: 1px solid var(--a11y-black-25); box-shadow: 0 3px 5px 0 #736ccb1a; + gap: 1rem; } .help-link { From 6f462fdff2e7b1e34dffc532d64aa18ea87d1700 Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Thu, 10 Oct 2024 17:24:36 +0800 Subject: [PATCH 27/35] chore: update title icon --- src/static/ejs/report.ejs | 3 ++- src/static/ejs/summary.ejs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index 17bcbddb..6169f39c 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -14,7 +14,8 @@ <%- include('partials/styles/bootstrap') %> <%- include('partials/styles/highlightjs') %> <%- include('partials/styles/styles') %> diff --git a/src/static/ejs/summary.ejs b/src/static/ejs/summary.ejs index 186147c0..6757a79b 100644 --- a/src/static/ejs/summary.ejs +++ b/src/static/ejs/summary.ejs @@ -7,7 +7,8 @@ <%- include('partials/styles/summaryBootstrap') %> <%- include('partials/styles/highlightjs') %> <%- include('partials/styles/styles') %> From bdd590e6d1f672202fdb07e28197de1d14770027 Mon Sep 17 00:00:00 2001 From: KCas <78678795+CKodes@users.noreply.github.com> Date: Mon, 14 Oct 2024 13:52:35 +0800 Subject: [PATCH 28/35] chore: Rename to Oobee --- .dockerignore | 2 +- .github/workflows/docker-test.yml | 82 ++++----- .github/workflows/image.yml | 66 +++---- .gitignore | 4 +- Dockerfile | 12 +- INSTALLATION.md | 108 ++++++----- INTEGRATION.md | 167 +++++++++--------- README.md | 115 ++++++------ __mocks__/mock-report.html | 16 +- __mocks__/mockIssues.ts | 9 +- __mocks__/mock_all_issues/000000001.json | 12 +- __mocks__/mock_all_issues/000000002.json | 10 +- a11y-scan-results.zip | Bin 0 -> 1376935 bytes gitlab-pipeline-template.yml | 48 ++--- package.json | 10 +- scripts/a11y_shell.cmd | 6 +- scripts/a11y_shell.command | 2 +- scripts/a11y_shell.sh | 8 +- scripts/a11y_shell_ps.ps1 | 30 ++-- scripts/install_purple_dependencies.cmd | 8 +- scripts/install_purple_dependencies.command | 12 +- scripts/install_purple_dependencies.ps1 | 20 +-- src/cli.ts | 10 +- src/constants/common.ts | 42 +++-- src/constants/constants.ts | 5 +- src/constants/purpleAi.ts | 4 +- src/constants/questions.ts | 2 +- src/crawlers/custom/utils.ts | 18 +- src/crawlers/customAxeFunctions.ts | 2 +- src/index.ts | 11 +- src/logs.ts | 6 +- src/mergeAxeResults.ts | 18 +- src/npmIndex.ts | 30 ++-- .../ejs/partials/components/scanAbout.ejs | 12 +- .../ejs/partials/scripts/categorySummary.ejs | 10 +- .../ejs/partials/scripts/ruleOffcanvas.ejs | 14 +- src/static/ejs/partials/scripts/utils.ejs | 36 ++-- src/static/ejs/partials/summaryHeader.ejs | 2 +- src/static/ejs/partials/summaryMain.ejs | 2 +- src/static/ejs/report.ejs | 2 +- src/static/ejs/summary.ejs | 2 +- src/static/mustache/report.mustache | 22 +-- src/utils.ts | 31 ++-- 43 files changed, 519 insertions(+), 509 deletions(-) create mode 100644 a11y-scan-results.zip diff --git a/.dockerignore b/.dockerignore index d3c20e40..308b313d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -19,4 +19,4 @@ logs/ results/ ImageMagick-*/ errors.txt -a11y-scan-results.zip +oobee-scan-results.zip \ No newline at end of file diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml index fe05cb41..9c36342f 100644 --- a/.github/workflows/docker-test.yml +++ b/.github/workflows/docker-test.yml @@ -11,44 +11,44 @@ jobs: runs-on: ubuntu-latest steps: - - name: Checkout code - uses: actions/checkout@v2 - - - name: Build and run Docker container - run: | - # Build your Docker image (replace 'purple-a11y' and 'Dockerfile' with your image name and Dockerfile path) - docker build -t purple-a11y . - # Run the Docker container (adjust any options as needed) - docker run -dit --name purple-a11y-container purple-a11y - # Ensure the Docker container is running before running the next step - continue-on-error: true - - - name: Run Node CLI command inside the Docker container - run: | - # Execute a webisite crawl - docker exec purple-a11y-container npm run cli -- -u "${{ vars.A11Y_SCAN_URL }}" -c 2 -p "${{ vars.A11Y_SCAN_MAX_NUM_PAGES }}" -t "${{ vars.A11Y_SCAN_MAX_CONCURRENCY }}" -k "${{ github.actor }}:${{ github.actor }}@users.noreply.github.com" -b chromium || true - - - name: Print errors - run: | - docker exec purple-a11y-container cat errors.txt || true - - - name: Print logs - run: | - docker exec purple-a11y-container cat logs/*/*.txt || true - - name: Copy Results from Docker Container - run: docker cp purple-a11y-container:/app/results ./results - - - name: Zip Results - run: zip -r results.zip ./results - - - name: Upload Zip File - uses: actions/upload-artifact@v4 - with: - name: results - path: results.zip - - - name: Cleanup Docker container - run: | - # Stop and remove the Docker container - docker stop purple-a11y-container - docker rm purple-a11y-container + - name: Checkout code + uses: actions/checkout@v2 + + - name: Build and run Docker container + run: | + # Build your Docker image (replace 'oobee' and 'Dockerfile' with your image name and Dockerfile path) + docker build -t oobee . + # Run the Docker container (adjust any options as needed) + docker run -dit --name oobee-container oobee + # Ensure the Docker container is running before running the next step + continue-on-error: true + + - name: Run Node CLI command inside the Docker container + run: | + # Execute a webisite crawl + docker exec oobee-container npm run cli -- -u "${{ vars.OOBEE_SCAN_URL }}" -c 2 -p "${{ vars.OOBEE_SCAN_MAX_NUM_PAGES }}" -t "${{ vars.OOBEE_SCAN_MAX_CONCURRENCY }}" -k "${{ github.actor }}:${{ github.actor }}@users.noreply.github.com" -b chromium || true + + - name: Print errors + run: | + docker exec oobee-container cat errors.txt || true + + - name: Print logs + run: | + docker exec oobee-container cat logs/*/*.txt || true + - name: Copy Results from Docker Container + run: docker cp oobee-container:/app/results ./results + + - name: Zip Results + run: zip -r results.zip ./results + + - name: Upload Zip File + uses: actions/upload-artifact@v4 + with: + name: results + path: results.zip + + - name: Cleanup Docker container + run: | + # Stop and remove the Docker container + docker stop oobee-container + docker rm oobee-container diff --git a/.github/workflows/image.yml b/.github/workflows/image.yml index 0803fcfa..863b866f 100644 --- a/.github/workflows/image.yml +++ b/.github/workflows/image.yml @@ -1,74 +1,74 @@ -name: Push installation image +name: Push installation image -on: +on: workflow_dispatch: release: types: [published] jobs: - windows-install-purple: + windows-install-oobee: runs-on: windows-latest steps: - name: Check out repository code uses: actions/checkout@v3 with: - path: purple-a11y + path: oobee - name: Copy scripts to parent directory run: | - cp ${{github.workspace}}/purple-a11y/scripts/*.ps1 ${{github.workspace}} - cp ${{github.workspace}}/purple-a11y/scripts/*.cmd ${{github.workspace}} - cp ${{github.workspace}}/purple-a11y/scripts/*.xml ${{github.workspace}} - + cp ${{github.workspace}}/oobee/scripts/*.ps1 ${{github.workspace}} + cp ${{github.workspace}}/oobee/scripts/*.cmd ${{github.workspace}} + cp ${{github.workspace}}/oobee/scripts/*.xml ${{github.workspace}} + - name: Install Purple dependencies for Windows shell: pwsh - run: powershell.exe -NoProfile -ExecutionPolicy Bypass "& ${{github.workspace}}\install_purple_dependencies.ps1" - working-directory: ${{github.workspace}} + run: powershell.exe -NoProfile -ExecutionPolicy Bypass "& ${{github.workspace}}\install_oobee_dependencies.ps1" + working-directory: ${{github.workspace}} - name: Zip entire Purple folder (Windows) shell: pwsh - run: Compress-Archive -Path ${{github.workspace}}/* -DestinationPath purple-a11y-portable-windows.zip + run: Compress-Archive -Path ${{github.workspace}}/* -DestinationPath oobee-portable-windows.zip - name: Upload Windows artifact uses: actions/upload-artifact@v4 with: - name: purple-a11y-portable-windows - path: ./purple-a11y-portable-windows.zip + name: oobee-portable-windows + path: ./oobee-portable-windows.zip - name: Release Windows artifact uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: files: | - purple-a11y-portable-windows.zip - - mac-install-purple: + oobee-portable-windows.zip + + mac-install-oobee: runs-on: self-hosted environment: macos - + steps: - name: Clean Workspace Folder run: | - rm -rf ./* || true - rm -rf ./.??* || true - + rm -rf ./* || true + rm -rf ./.??* || true + - name: Check out repository code uses: actions/checkout@v3 with: - path: purple-a11y - + path: oobee + - name: Grant execute permissions for user run: chmod ugo+rwx ./scripts/*.command ./scripts/*.sh - working-directory: purple-a11y + working-directory: oobee - name: Copy scripts to parent directory run: | - cp ./purple-a11y/scripts/{*.command,*.sh,*.xml} ${{ github.workspace }} + cp ./oobee/scripts/{*.command,*.sh,*.xml} ${{ github.workspace }} - name: Install Purple dependencies for MacOS run: | - ./install_purple_dependencies.command + ./install_oobee_dependencies.command - name: Sign required binaries for MacOS run: | @@ -77,7 +77,7 @@ jobs: # Paths to the binaries you want to sign only ending with .node BINARIES=($(find . -type f -name "*.node" ! -path "*.framework/*" ! -path "*.dSYM/*")) - + # Loop through the binary paths and sign each one with a secure timestamp for binary in "${BINARIES[@]}"; do # Check if the binary is already signed @@ -88,20 +88,20 @@ jobs: echo "Failed to sign: $binary" fi done - + - name: Zip entire Purple folder (Mac) run: | - zip purple-a11y-portable-mac.zip -y -r ./ - + zip oobee-portable-mac.zip -y -r ./ + - name: Upload Mac artifact uses: actions/upload-artifact@v4 with: - name: purple-a11y-portable-mac - path: ./purple-a11y-portable-mac.zip - + name: oobee-portable-mac + path: ./oobee-portable-mac.zip + - name: Release Mac artifact uses: softprops/action-gh-release@v1 if: startsWith(github.ref, 'refs/tags/') with: files: | - purple-a11y-portable-mac.zip + oobee-portable-mac.zip diff --git a/.gitignore b/.gitignore index 4009b0df..8210b3d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ dist node_modules .vscode -.a11y_storage +.oobee_storage results/ logs/ debug*.txt @@ -19,7 +19,7 @@ nodejs-* amazon-corretto-* verapdf* ms-playwright/ -a11y-scan-results*.zip +oobee-scan-results*.zip PHScan_*/ Upload Files/ Chromium Support/ diff --git a/Dockerfile b/Dockerfile index 6b3cbfdb..901f148f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Use Node LTS alpine distribution FROM node:lts-alpine3.18 -# Installation of packages for purple-a11y and chromium +# Installation of packages for oobee and chromium RUN apk add build-base gcompat g++ make python3 zip bash git chromium openjdk11-jre # Installation of VeraPDF @@ -22,13 +22,13 @@ RUN echo $' \n\ \n\ ' >> /opt/verapdf-auto-install-docker.xml -RUN wget "https://github.com/GovTechSG/purple-a11y/releases/download/cache/verapdf-installer.zip" -P /opt +RUN wget "https://github.com/GovTechSG/oobee/releases/download/cache/verapdf-installer.zip" -P /opt RUN unzip /opt/verapdf-installer.zip -d /opt RUN latest_version=$(ls -d /opt/verapdf-greenfield-* | sort -V | tail -n 1) && [ -n "$latest_version" ] && \ "$latest_version/verapdf-install" "/opt/verapdf-auto-install-docker.xml" RUN rm -rf /opt/verapdf-installer.zip /opt/verapdf-greenfield-* -# Set purple-a11y directory +# Set oobee directory WORKDIR /app # Copy package.json to working directory, perform npm install before copying the remaining files @@ -47,11 +47,11 @@ RUN npm install --force --omit=dev RUN npx playwright install chromium webkit # Add non-privileged user -RUN addgroup -S purple && adduser -S -G purple purple -RUN chown -R purple:purple ./ +RUN addgroup -S oobee && adduser -S -G oobee oobee +RUN chown -R oobee:oobee ./ # Run everything after as non-privileged user. -USER purple +USER oobee # Copy application and support files COPY . . diff --git a/INSTALLATION.md b/INSTALLATION.md index 86d654d5..cb6e3ae1 100644 --- a/INSTALLATION.md +++ b/INSTALLATION.md @@ -1,60 +1,68 @@ ## Installation Guide -Purple A11y is provided as a portable distribution which minimises installation steps required for Windows and Mac. +Oobee is provided as a portable distribution which minimises installation steps required for Windows and Mac. -### About Purple A11y -Purple A11y is a customisable, automated accessibility testing tool that allows software development teams to find and fix accessibility problems to improve persons with disabilities (PWDs) access to digital services. +### About Oobee + +Oobee is a customisable, automated accessibility testing tool that allows software development teams to find and fix accessibility problems to improve persons with disabilities (PWDs) access to digital services. ### System Requirements -* Purple A11y can run on MacOS Big Sur or above, and a [supported](https://learn.microsoft.com/en-us/windows/release-health/supported-versions-windows-client) version of Windows 10 (64-bit) or Windows 11. -* Google Chrome browser is [installed](https://www.google.com/chrome). -* One-time Internet access is needed to download and install Purple A11y Desktop. -* You are recommended to be logged on to an admin user to run Purple A11y Desktop. + +- Oobee can run on MacOS Big Sur or above, and a [supported](https://learn.microsoft.com/en-us/windows/release-health/supported-versions-windows-client) version of Windows 10 (64-bit) or Windows 11. +- Google Chrome browser is [installed](https://www.google.com/chrome). +- One-time Internet access is needed to download and install Oobee Desktop. +- You are recommended to be logged on to an admin user to run Oobee Desktop. ### Windows + Click here for Windows setup instructions #### Download Portable Copy -* Download and extract latest [purple-a11y-portable-windows.zip](https://github.com/GovTechSG/purple-a11y/releases/latest/download/purple-a11y-portable-windows.zip). -* Tip: To extract files, right-click the Compressed zip file and click "Extract All…" in the context menu. -#### Run Purple A11y - * Navigate to the folder containing purple-a11y-portable-windows. - * Double-click `a11y_shell.cmd` (Windows Command Script file). - +- Download and extract latest [oobee-portable-windows.zip](https://github.com/GovTechSG/oobee/releases/latest/download/oobee-portable-windows.zip). +- Tip: To extract files, right-click the Compressed zip file and click "Extract All…" in the context menu. + +#### Run Oobee + +- Navigate to the folder containing oobee-portable-windows. +- Double-click `oobee_shell.cmd` (Windows Command Script file). + + +- A Windows Command Prompt window should open with contents as illustrated below. `oobee_shell` will automatically prepare your system to run Oobee. - * A Windows Command Prompt window should open with contents as illustrated below. `a11y_shell` will automatically prepare your system to run Purple a11y. ``` -a11y Shell - Created By younglim - NO WARRANTY PROVIDED +oobee Shell - Created By younglim - NO WARRANTY PROVIDED ================================================================ -INFO: Stored current working directory at C:\Users\a11y\Downloads\purple-a11y-portable-windows +INFO: Stored current working directory at C:\Users\oobee\Downloads\oobee-portable-windows INFO: Set path to node for this session INFO: Set path to node_modules for this session INFO: Set path to npm-global for this session INFO: Set path to Playwright cache for this session INFO: Set path to ImageMagick for this session -INFO: Set path to purple-a11y for this session +INFO: Set path to oobee for this session -PS C:\Users\username\Downloads\purple-a11y-portable-windows> +PS C:\Users\username\Downloads\oobee-portable-windows> ``` +- Type in the following commands into the window. The following commands will navigate your Command Prompt window to the `oobee` sub-directory and initiate a scan - * Type in the following commands into the window. The following commands will navigate your Command Prompt window to the `purple-a11y` sub-directory and initiate a scan ``` -cd purple-a11y +cd oobee node index ``` - * If a Windows Firewall prompt appears, if you have administrator rights, click "Allow" or "Allow access". Click "Cancel" if you do not have administrator rights. - - - * You should then see your Windows Command Prompt window updated with the following contents +- If a Windows Firewall prompt appears, if you have administrator rights, click "Allow" or "Allow access". Click "Cancel" if you do not have administrator rights. + + + +- You should then see your Windows Command Prompt window updated with the following contents + ``` -PS C:\Users\username\Downloads\purple-a11y-portable-windows> cd purple-a11y -PS C:\Users\username\Downloads\purple-a11y-portable-windows\purple-a11y> node index +PS C:\Users\username\Downloads\oobee-portable-windows> cd oobee +PS C:\Users\username\Downloads\oobee-portable-windows\oobee> node index ┌────────────────────────────────────────────────────────────┐ │ Welcome to A11y Accessibility Testing Tool! │ │ We recommend using Chrome browser for the best experience. │ @@ -67,32 +75,36 @@ PS C:\Users\username\Downloads\purple-a11y-portable-windows\purple-a11y> node in custom flow ``` - * Follow the steps at [Features](https://github.com/GovTechSG/purple-a11y#features) for more information on how to run a scan. +- Follow the steps at [Features](https://github.com/GovTechSG/oobee#features) for more information on how to run a scan. ### MacOS + Click here for MacOS setup instructions #### Download Portable Copy - * Download and extract [purple-a11y-portable-mac.zip](https://github.com/GovTechSG/purple-a11y/releases/latest/download/purple-a11y-portable-mac.zip) version. - * Tip: To extract files in Mac, double-click on `purple-a11y-portable-mac.zip` file, usually located at your Downloads folder. A new folder with the name `purple-a11y-portable-mac` will appear in Finder. -#### Run Purple A11y - * Navigate to the folder `purple-a11y-portable-mac`, usually located at your Downloads folder. - * Right-click `a11y_shell.command`. Then click `Open` in the context menu. - +- Download and extract [oobee-portable-mac.zip](https://github.com/GovTechSG/oobee/releases/latest/download/oobee-portable-mac.zip) version. +- Tip: To extract files in Mac, double-click on `oobee-portable-mac.zip` file, usually located at your Downloads folder. A new folder with the name `oobee-portable-mac` will appear in Finder. + +#### Run Oobee + +- Navigate to the folder `oobee-portable-mac`, usually located at your Downloads folder. +- Right-click `oobee_shell.command`. Then click `Open` in the context menu. + + +- A prompt as follows will appear like below. Click `Open`. + - * A prompt as follows will appear like below. Click `Open`. - +- A Terminal window should open with contents as illustrated below. `oobee_shell` will automatically prepare your system to run Oobee. - * A Terminal window should open with contents as illustrated below. `a11y_shell` will automatically prepare your system to run Purple A11y. ``` Last login: Thu Mar 16 10:48:05 on ttys002 -/Users/username/Downloads/purple-a11y-portable-mac/a11y_shell.command ; exit; -username@hostname ~ % /Users/username/Downloads/purple-a11y-portable-mac/a11y_shell.command ; exit; -a11y Shell - Created By younglim - NO WARRANTY PROVIDED +/Users/username/Downloads/oobee-portable-mac/oobee_shell.command ; exit; +username@hostname ~ % /Users/username/Downloads/oobee-portable-mac/oobee_shell.command ; exit; +oobee Shell - Created By younglim - NO WARRANTY PROVIDED ================================================================ INFO: Setting path to node for this session @@ -101,19 +113,21 @@ INFO: Set path to Playwright cache for this session INFO: Set symbolic link to ImageMagick INFO: Set path to ImageMagick binaries INFO: Removing com.apple.quarantine attributes for required binaries to run -username@hostname purple-a11y-portable-mac % +username@hostname oobee-portable-mac % ``` - * Type in the following commands into the window. The following commands will navigate your Terminal window to the `purple-a11y` sub-directory and initiate a scan - ``` -cd purple-a11y +- Type in the following commands into the window. The following commands will navigate your Terminal window to the `oobee` sub-directory and initiate a scan + +``` +cd oobee node index ``` - * You should then see your Terminal window updated with the following contents +- You should then see your Terminal window updated with the following contents + ``` -username@hostname purple-a11y-portable-mac % cd purple-a11y -username@hostname purple-a11y % node index +username@hostname oobee-portable-mac % cd oobee +username@hostname oobee % node index ┌────────────────────────────────────────────────────────────┐ │ Welcome to A11y Accessibility Testing Tool! │ │ We recommend using Chrome browser for the best experience. │ @@ -126,5 +140,5 @@ username@hostname purple-a11y % node index custom flow ``` - * Follow the steps at [Features](https://github.com/GovTechSG/purple-a11y#features) for more information on how to run a scan. +- Follow the steps at [Features](https://github.com/GovTechSG/oobee#features) for more information on how to run a scan. diff --git a/INTEGRATION.md b/INTEGRATION.md index d5dbef6f..ff4265f4 100644 --- a/INTEGRATION.md +++ b/INTEGRATION.md @@ -1,6 +1,6 @@ -## Integrating Purple A11y with end-to-end testing frameworks +## Integrating Oobee with end-to-end testing frameworks -Purple A11y provides functionalities that makes it possible to be integrated with end-to-end testing frameworks such as [Cypress](https://www.cypress.io/) and [Playwright](https://playwright.dev/). +Oobee provides functionalities that makes it possible to be integrated with end-to-end testing frameworks such as [Cypress](https://www.cypress.io/) and [Playwright](https://playwright.dev/). ### Prerequisites @@ -10,40 +10,40 @@ In order to use this functionality, the testing framework must support: - Injection of JavaScript into the document that is being tested. - Execution of JavaScript in the context of the document and retrieval of results back into the NodeJS environment after execution. -### How to include Purple A11y in your project +### How to include Oobee in your project -1. Add Purple A11y to your project by running the following command: +1. Add Oobee to your project by running the following command: - `npm install --save-dev @govtechsg/purple-hats` + `npm install --save-dev @govtechsg/oobee` -2. In the file of choice, import Purple A11y using: +2. In the file of choice, import Oobee using: - `import purpleA11yInit from '@govtechsg/purple-hats'` + `import oobeeA11yInit from '@govtechsg/oobee'` - Note that Purple A11y should be imported in a script that runs in a NodeJS environment. + Note that Oobee should be imported in a script that runs in a NodeJS environment. -3. Create an instance of Purple A11y with: +3. Create an instance of Oobee with: - `const purpleA11y = await purpleA11yInit(entryUrl)` + `const oobeeA11y = await oobeeA11yInit(entryUrl)` - `entryUrl` should be a valid URL referring to the domain of the website to be scanned with Purple A11y. + `entryUrl` should be a valid URL referring to the domain of the website to be scanned with Oobee. ### API Reference -#### `async purpleA11yInit(entryUrl, testLabel, name, email, includeScreenshots, viewportSettings, thresholds, scanAboutMetadata)` +#### `async oobeeA11yInit(entryUrl, testLabel, name, email, includeScreenshots, viewportSettings, thresholds, scanAboutMetadata)` -Returns an instance of Purple A11y +Returns an instance of Oobee ##### Parameters - `entryUrl` - - Initial URL to start the purple a11y scan + - Initial URL to start the oobee oobee scan - `testLabel` - Label for test in report - `name` - - For Purple A11y data collection purposes + - For Oobee data collection purposes - `email` - - For Purple A11y data collection purposes + - For Oobee data collection purposes - `includeScreenshots` (optional) - Include screenshots of affected elements in the report. Defaults to false. - `viewportSettings` (optional) @@ -53,9 +53,9 @@ Returns an instance of Purple A11y - `scanAboutMetadata` (optional) - Include additional information in the Scan About section of the report by passing in a JSON object. - `zip` (optional) - - Name of the generated zip of Purple A11y results at the end of scan. Defaults to "a11y-scan-results". + - Name of the generated zip of Oobee results at the end of scan. Defaults to "oobee-scan-results". -#### Purple A11y Instance +#### Oobee Instance ##### Properties @@ -109,28 +109,28 @@ Returns: Checks the accumulated issue occurrences count against the specified threshold. -- Terminates purpleA11y instance and throws an error if the number of accumulated mustFix or goodToFix issue occurrences exceeds either of the specified thresholds. +- Terminates oobeeA11y instance and throws an error if the number of accumulated mustFix or goodToFix issue occurrences exceeds either of the specified thresholds. `async terminate()` -Stops the Purple A11y instance and generates the scan report and other scan result artifacts. Returns the name of the generated folder containing the results. +Stops the Oobee instance and generates the scan report and other scan result artifacts. Returns the name of the generated folder containing the results. ### How to use Example usages for Cypress and Playwright can be found in [this section](#example-usages). -With reference to an instance of Purple A11y as `purpleA11y`: +With reference to an instance of Oobee as `oobeeA11y`: -1. Fetch the necessary scripts needed to be injected to document to be scanned by executing `purpleA11y.getScripts()`. The scripts will be returned as a string. +1. Fetch the necessary scripts needed to be injected to document to be scanned by executing `oobeeA11y.getScripts()`. The scripts will be returned as a string. 2. Inject the scripts into the document to be scanned. The easiest way that this can be done is by using `eval()` in the document's environment. - Note that this step needs to be done for every page visited. 3. Run a scan by executing `runA11yScan()` in the document's environment. - By default, the scan will be run for the entire page. - It is possible to run the scan for specific sections or elements in the page. One way to do this is to pass an array of CSS selectors of the elements to be scanned into `runA11yScan`. For example, `runA11yScan(['#my-component', 'button'])`. Other acceptable forms of argument can be found [here](https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#context-parameter). -4. Pass the scan results back into the NodeJS environment where `purpleA11y` is in. -5. Push the results using `await purpleA11y.pushScanResults(scanResults)`. +4. Pass the scan results back into the NodeJS environment where `oobeeA11y` is in. +5. Push the results using `await oobeeA11y.pushScanResults(scanResults)`. 6. Repeat steps 2-5 as many times as desired. -7. Terminate Purple A11y by using `await purpleA11y.terminate()`. A folder containing the details and report of your scan will be created, under the directory `results` which can be found in your project's root directory. +7. Terminate Oobee by using `await oobeeA11y.terminate()`. A folder containing the details and report of your scan will be created, under the directory `results` which can be found in your project's root directory. ### Example usages @@ -153,11 +153,11 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install cypress @govtechsg/purple-hats --save-dev +Install the following node dependencies by running npm install cypress @govtechsg/oobee --save-dev -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. @@ -165,7 +165,7 @@ Navigate to node_modules/@govtechsg/purple-hats and run npm i Create cypress.config.js with the following contents, and change your Name, E-mail address, and boolean value for whether rule items requiring manual review in the report should be displayed below: import { defineConfig } from "cypress"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; // viewport used in tests to optimise screenshots const viewportSettings = { width: 1920, height: 1040 }; @@ -174,9 +174,9 @@ Create cypress.config.js with the following contents, and change yo // additional information to include in the "Scan About" section of the report const scanAboutMetadata = { browser: 'Chrome (Desktop)' }; // name of the generated zip of the results at the end of scan - const resultsZipName = "a11y-scan-results" + const resultsZipName = "oobee-scan-results" - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Cypress Scan", // label for test "Your Name", @@ -196,20 +196,20 @@ Create cypress.config.js with the following contents, and change yo setupNodeEvents(on, _config) { on("task", { getPurpleA11yScripts() { - return purpleA11y.getScripts(); + return oobeeA11y.getScripts(); }, async pushPurpleA11yScanResults({res, metadata, elementsToClick}) { - return await purpleA11y.pushScanResults(res, metadata, elementsToClick); + return await oobeeA11y.pushScanResults(res, metadata, elementsToClick); }, returnResultsDir() { - return `results/${purpleA11y.randomToken}_${purpleA11y.scanDetails.urlsCrawled.scanned.length}pages/report.html`; + return `results/${oobeeA11y.randomToken}_${oobeeA11y.scanDetails.urlsCrawled.scanned.length}pages/report.html`; }, finishPurpleA11yTestCase() { - purpleA11y.testThresholds(); + oobeeA11y.testThresholds(); return null; }, async terminatePurpleA11y() { - return await purpleA11y.terminate(); + return await oobeeA11y.terminate(); }, }); }, @@ -231,7 +231,7 @@ Create a sub-folder and file cypress/support/e2e.js with the follow const { elementsToScan, elementsToClick, metadata } = items; const res = await win.runA11yScan(elementsToScan); cy.task("pushPurpleA11yScanResults", {res, metadata, elementsToClick}).then((count) => { return count }); - cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }); }); @@ -242,9 +242,9 @@ Create a sub-folder and file cypress/support/e2e.js with the follow Create cypress/e2e/spec.cy.js with the following contents: describe("template spec", () => { - it("should run purple A11y", () => { + it("should run oobee A11y", () => { cy.visit( - "https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm" + "https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm" ); cy.injectPurpleA11yScripts(); cy.runPurpleA11yScan(); @@ -261,7 +261,7 @@ Create cypress/e2e/spec.cy.js with the following contents: }); Run your test with npx cypress run. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -284,9 +284,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install cypress @types/cypress @govtechsg/purple-hats typescript --save-dev +Install the following node dependencies by running npm install cypress @types/cypress @govtechsg/oobee typescript --save-dev Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -302,9 +303,9 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. @@ -312,7 +313,7 @@ Navigate to node_modules/@govtechsg/purple-hats and run npm i Create cypress.config.ts with the following contents, and change your Name, E-mail address, and boolean value for whether rule items requiring manual review in the report should be displayed below: import { defineConfig } from "cypress"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; interface ViewportSettings { width: number; @@ -335,9 +336,9 @@ Create cypress.config.ts with the following contents, and change yo // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; // name of the generated zip of the results at the end of scan - const resultsZipName: string = "a11y-scan-results" + const resultsZipName: string = "oobee-scan-results" - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Cypress Scan", // label for test "Your Name", @@ -357,20 +358,20 @@ Create cypress.config.ts with the following contents, and change yo setupNodeEvents(on, _config) { on("task", { getPurpleA11yScripts(): string { - return purpleA11y.getScripts(); + return oobeeA11y.getScripts(); }, async pushPurpleA11yScanResults({res, metadata, elementsToClick}: { res: any, metadata: any, elementsToClick: any[] }): Promise<{ mustFix: number, goodToFix: number }> { - return await purpleA11y.pushScanResults(res, metadata, elementsToClick); + return await oobeeA11y.pushScanResults(res, metadata, elementsToClick); }, returnResultsDir(): string { - return `results/${purpleA11y.randomToken}_${purpleA11y.scanDetails.urlsCrawled.scanned.length}pages/reports/report.html`; + return `results/${oobeeA11y.randomToken}_${oobeeA11y.scanDetails.urlsCrawled.scanned.length}pages/reports/report.html`; }, finishPurpleA11yTestCase(): null { - purpleA11y.testThresholds(); + oobeeA11y.testThresholds(); return null; }, async terminatePurpleA11y(): Promise { - return await purpleA11y.terminate(); + return await oobeeA11y.terminate(); }, }); }, @@ -394,7 +395,7 @@ Create a sub-folder and file src/cypress/support/e2e.ts with the fo const { elementsToScan, elementsToClick, metadata } = items; const res = await win.runA11yScan(elementsToScan); cy.task("pushPurpleA11yScanResults", {res, metadata, elementsToClick}).then((count) => { return count }); - cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }); }); @@ -405,9 +406,9 @@ Create a sub-folder and file src/cypress/support/e2e.ts with the fo Create src/cypress/e2e/spec.cy.ts with the following contents: describe("template spec", () => { - it("should run purple A11y", () => { + it("should run oobee A11y", () => { cy.visit( - "https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm" + "https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm" ); cy.injectPurpleA11yScripts(); cy.runPurpleA11yScan(); @@ -424,6 +425,7 @@ Create src/cypress/e2e/spec.cy.ts with the following contents: }); Create cypress.d.ts in the root directory with the following contents: + ``` declare namespace Cypress { interface Chainable { @@ -447,7 +449,7 @@ interface Window { Compile your typescript code with npx tsc. Run your test with npx cypress run. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -460,19 +462,19 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee --save-dev and npx playwright install -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -On your project's root folder, create a Playwright test file purpleA11y-playwright-demo.js: +On your project's root folder, create a Playwright test file oobeeA11y-playwright-demo.js: import { chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; // viewport used in tests to optimise screenshots const viewportSettings = { width: 1920, height: 1040 }; @@ -481,7 +483,7 @@ On your project's root folder, create a Playwright test file purpleA11y-pl // additional information to include in the "Scan About" section of the report const scanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -504,12 +506,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -520,12 +522,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); -Run your test with node purpleA11y-playwright-demo.js . +Run your test with node oobeeA11y-playwright-demo.js . -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -535,9 +537,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats typescript --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee typescript --save-dev and npx playwright install Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -552,17 +555,17 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -Create a sub-folder and Playwright test file src/purpleA11y-playwright-demo.ts with the following contents: +Create a sub-folder and Playwright test file src/oobeeA11y-playwright-demo.ts with the following contents: import { Browser, BrowserContext, Page, chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; declare const runA11yScan: (elementsToScan?: string[]) => Promise; @@ -587,7 +590,7 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -610,12 +613,12 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -777,6 +780,6 @@ You will see Purple A11y results generated in results folder. }); }; - runScript(); + runScript(); diff --git a/README.md b/README.md index 4bcc2aef..57625f0b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# Purple A11y +# Oobee -[Purple A11y](https://go.gov.sg/purple-a11y-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). - -This is the engine and command-line interface (CLI) for Purple A11y. For a desktop graphical user interface (GUI), check out [Purple A11y Desktop](https://go.gov.sg/purple-a11y). The official application can only be downloaded at [https://go.gov.sg/purple-a11y-cicd](https://go.gov.sg/purple-a11y-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. +[Oobee](https://go.gov.sg/oobee-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). +This is the engine and command-line interface (CLI) for Oobee. For a desktop graphical user interface (GUI), check out [Oobee Desktop](https://go.gov.sg/oobee). The official application can only be downloaded at [https://go.gov.sg/oobee-cicd](https://go.gov.sg/oobee-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. ## Technology Stack @@ -15,27 +14,31 @@ This is the engine and command-line interface (CLI) for Purple A11y. For a desk 6. [Corretto](https://aws.amazon.com/corretto) 7. [VeraPDF](https://github.com/veraPDF/veraPDF-apps) -## Using Purple A11y as a NodeJS module +## Using Oobee as a NodeJS module -If you wish to use Purple A11y as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. +If you wish to use Oobee as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. ## Prerequisites and Installations -### Portable Purple A11y +### Portable Oobee -Portable Purple A11y is the recommended way to run Purple A11y as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Purple A11y. +Portable Oobee is the recommended way to run Oobee as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Oobee. ### Manual Installation Please ensure the following requirements are met: #### Node.js + - A Node distribution of 20 (LTS) or above. - To check your version of Node, go into terminal and paste the command bellow + ```shell node -v ``` -- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + +- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + ```shell # Install NodeJS version with NVM nvm install --lts @@ -43,20 +46,26 @@ nvm install --lts # For subsequent use, you will need to run the command below each time you open a new terminal nvm use --lts ``` + - Install the required NPM packages with `npm install`. - Build the project with `npm run build` before you try to run it with `npm start`. #### Java JRE/JDK + - A JRE/JDK distribution of version 11 or above. - To check your version of Java, go into terminal and paste the command bellow + ```shell java --version ``` + - If you do not have java, you can consider installing [Corretto](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html) distribution of OpenJDK. #### VeraPDF -- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. + +- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. - Ensure you have VeraPDF set in PATH then verify verapdf is installed correctly: + ```shell # Invoke the VeraPDF installer # Windows users should use vera-install.bat instead of vera-install @@ -77,22 +86,22 @@ Please refer to [Troubleshooting section](#troubleshooting) for more information ## Features -Purple A11y can perform the following to scan the target URL. +Oobee can perform the following to scan the target URL. -- To **run** Purple A11y in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. +- To **run** Oobee in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. - Results will be compiled in JSON format, followed by generating a HTML report. > NOTE: For your initial scan, there may be some loading time required before use. Purple-A11y will also ask for your name and email address and collect your app usage data to personalise your experience. Your information fully complies with [GovTech’s Privacy Policy](https://www.tech.gov.sg/privacy/). #### Delete/Edit Details + > You may delete and edit your cached name and e-mail address by running the following command to delete `userData.txt`: -> - Windows (PowerShell): `rm "$env:APPDATA\Purple A11y\userData.txt"` -> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Purple A11y/userData.txt"` +> - Windows (PowerShell): `rm "$env:APPDATA\Oobee\userData.txt"` +> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Oobee/userData.txt"` If `userData.txt` does not exists just run `npm start`. - ### Scan Selection You can interact via your arrow keys. @@ -100,7 +109,7 @@ You can interact via your arrow keys. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience.│ │ │ │ Welcome back User! │ @@ -119,14 +128,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? (Y/n) No +? Do you want oobee to run in the background? (Y/n) No ``` ### Sitemap Scan @@ -134,14 +143,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL or file path to sitemap, or drag and drop a sitemap file here: https://www.sitemaps.org/sitemap.xml @@ -154,7 +163,7 @@ Headless mode would allow you to run the scan in the background. If you would li Scanning website... -#purple-a11y will then start scraping from the file link provided above. +#oobee will then start scraping from the file link provided above. #Console results ``` @@ -170,14 +179,14 @@ If the sitemap URL provided is invalid, an error message will be prompted for yo ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? Yes +? Do you want oobee to run in the background? Yes ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL of website: https://www.domain.org @@ -191,19 +200,19 @@ If the website URL provided is invalid, an error message will be prompted for yo ### Customised Mobile Device Scan -``` shell +```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) (Use arrow keys) -❯ Desktop +❯ Desktop Mobile Custom ``` @@ -212,14 +221,14 @@ Choose `Mobile` for a default mobile screen size scan and `Custom` to choose a d ### Custom flow -Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. +Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. 1. Start by choosing the `Custom flow` in the menu selection. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ @@ -229,10 +238,10 @@ Custom flow allows you to specify a user journey by enabling you to click the sc Sitemap Website ❯ Custom - ``` +``` 1. Specify the URL of the starting page you wish to scan -2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. +2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. 3. You may drag the top black bar to the bottom of the page in the event it prevents you from viewing / blocking certain page elements. 4. Close the Chrome window to end the scan. @@ -240,11 +249,10 @@ Other options: - You can specify sites to exclude from accessibility scan (e.g. login page) by adding a pattern of the domain to `exclusions.txt`. An example of `exclusions.txt`: -``` txt +```txt \.*login.singpass.gov.sg\.* ``` - #### Known Issues If the custom flow fails to start, you might be running multiple versions of Playwright. Re-install Playwright: @@ -259,9 +267,8 @@ npx playwright@1.27.1 install ### CLI Mode -CLI mode is designed to be run in continuous integration (CI) environment. - Run `npm run cli` for a set of command-line parameters available. - +CLI mode is designed to be run in continuous integration (CI) environment. +Run `npm run cli` for a set of command-line parameters available. ```shell Usage: npm run cli -- -c -d -w -If the device name contains ```(``` and ```)```, wrap the device name in single quotes when entered into the CLI. -Please note that ```-d``` and ```-w``` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. +If the device name contains `(` and `)`, wrap the device name in single quotes when entered into the CLI. +Please note that `-d` and `-w` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' +npm run cli -- -c 2 -o oobee-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' ``` If the site you want to scan has a query string wrap the link in single quotes when entered into the CLI. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with a custom screen width '360', run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with a custom screen width '360', run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u "http://localhost:8000" -w 360 +npm run cli -- -c 2 -o oobee-scan-results.zip -u "http://localhost:8000" -w 360 ``` ## Report -Once a scan of the site is completed. + +Once a scan of the site is completed. A report will be downloaded into the current working directory. ## Accessibility Scan Results -Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). +Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). -For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). +For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). ## Troubleshooting @@ -503,12 +511,12 @@ Please refer to the information below to assist in debugging. Most errors below **Issue**: When your Node.js version is incompatible, you may face the following syntax error. - ```shell const URL_NO_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line ^ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@:%\._\+~#=]{0,254}[\p{L}0-9]\.[a-z]{2,63}(:\d{1,5})?(/[-\p{L}0-9@:%_\+.~#?&//=\(\)]*)?/: Invalid escape ``` + **Solution**: Install Node.js versions >= 20, i.e. Node.js v20 and above. ### Compiled against a different Node.js version @@ -516,7 +524,7 @@ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@ **Issue**: When you switch between different versions of Node.js in your environment, you may face the following error. ```shell -/purple-a11y/node_modules/bindings/bindings.js:91 +/oobee/node_modules/bindings/bindings.js:91 throw e ^ @@ -531,15 +539,15 @@ the module (for instance, using `npm rebuild` or `npm install`). ### dyld Error -**Issue**: Not able to run Purple A11y due to the following error shown below +**Issue**: Not able to run Oobee due to the following error shown below ```shell dyld: lazy symbol binding failed: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace dyld: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /PURPLE_A11y/purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /PURPLE_A11y/oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace zsh: abort node index.js @@ -554,7 +562,7 @@ zsh: abort node index.js **Limitation**: Due to animations causing elements to shift out of the viewport after an Axe scan, there's a risk of element screenshots timing out within 5 seconds if the element is not found. This known issue is particularly prevalent in scenarios like carousels with interval-based transitions. -## FAQ +## FAQ ### How do I limit number of pages scanned? @@ -566,9 +574,8 @@ To do this, run CLI mode `npm run cli --` with the needed settings and specify ` We recommend looking at our **Technology Stack** to understand the usage of each component. Take your time to understand. - ## Additional Information on Data -Purple A11y uses third-party open-source tools that may be downloaded over the Internet during the installation process of Purple A11y. Users should be aware of the libraries used by examining `package.json`. +Oobee uses third-party open-source tools that may be downloaded over the Internet during the installation process of Oobee. Users should be aware of the libraries used by examining `package.json`. -Purple A11y may send information to the website, URL and HTML code snippets where the user chooses to initiate a Purple A11y scan for telemetry purposes. +Oobee may send information to the website, URL and HTML code snippets where the user chooses to initiate a Oobee scan for telemetry purposes. diff --git a/__mocks__/mock-report.html b/__mocks__/mock-report.html index b08801be..8ca6ee93 100644 --- a/__mocks__/mock-report.html +++ b/__mocks__/mock-report.html @@ -523,11 +523,11 @@ body.dark .footer { background-color: #272727; } - #a11y-table { + #oobee-table { background-color: #fff; width: 100%; } - body.dark #a11y-table { + body.dark #oobee-table { background-color: #272727; } table.dataTable { @@ -1117,7 +1117,7 @@ Accessibility Report - + IMPACT @@ -1151,7 +1151,7 @@ Accessibility Report @@ -1204,7 +1204,7 @@ Accessibility Report @@ -1257,7 +1257,7 @@ Accessibility Report @@ -1310,7 +1310,7 @@ Accessibility Report @@ -1374,7 +1374,7 @@ Accessibility Report diff --git a/src/static/ejs/partials/scripts/categorySummary.ejs b/src/static/ejs/partials/scripts/categorySummary.ejs index 6545b94a..9a2ff175 100644 --- a/src/static/ejs/partials/scripts/categorySummary.ejs +++ b/src/static/ejs/partials/scripts/categorySummary.ejs @@ -51,8 +51,8 @@ filteredItems[category].rules.forEach((rule, index) => { const buttonAriaLabel = `${rule.description}, ${rule.totalItems} occurrences`; - const purpleAiSvgId = `${category}-${rule.rule}-${index}`; - const isPurpleAiRule = purpleAiRules.includes(rule.rule); + const oobeeAiSvgId = `${category}-${rule.rule}-${index}`; + const isPurpleAiRule = oobeeAiRules.includes(rule.rule); // START new createElementFromString const ruleItem = createElementFromString(` @@ -67,8 +67,8 @@ ${ isPurpleAiRule ? `aria-describedby="containsAISuggestions" - onfocus="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" - onblur="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" + onfocus="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" + onblur="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" onmousedown="event.preventDefault()"` : `` } @@ -83,7 +83,7 @@ ${htmlEscapeString(rule.description)} ${ isPurpleAiRule - ? ` diff --git a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs index 38420722..ef8da4bc 100644 --- a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +++ b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs @@ -97,7 +97,7 @@ category summary is clicked %> `), ); - if (purpleAiRules.includes(selectedRule.rule)) { + if (oobeeAiRules.includes(selectedRule.rule)) { document.querySelector('#expandedRuleAiFeedback').style.display = 'block'; } else { document.querySelector('#expandedRuleAiFeedback').style.display = 'none'; @@ -535,10 +535,10 @@ category summary is clicked %> const buttonDivForAiFeedback = `${buttonAIId}-${index}`; const aiErrorDiv = `${errorAIId}-${index}`; let itemCard; - const isPurpleAiRule = purpleAiRules.includes(ruleInCategory.rule); - let purpleAiQueryLabel; + const isPurpleAiRule = oobeeAiRules.includes(ruleInCategory.rule); + let oobeeAiQueryLabel; if (isPurpleAiRule) { - purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); + oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); } itemCard = createElementFromString(` @@ -621,7 +621,7 @@ category summary is clicked %> AI suggestion - ${purpleAiQueryLabel.hasNetworkError ? + ${oobeeAiQueryLabel.hasNetworkError ? ` Generate response ` : - (purpleAiQueryLabel.label ? + (oobeeAiQueryLabel.label ? ` diff --git a/src/static/ejs/partials/scripts/utils.ejs b/src/static/ejs/partials/scripts/utils.ejs index 9c4b18f7..3b573640 100644 --- a/src/static/ejs/partials/scripts/utils.ejs +++ b/src/static/ejs/partials/scripts/utils.ejs @@ -6,8 +6,8 @@ return tempContainer.firstChild; } - const purpleAiHtmlETL = <%- purpleAi.htmlETL %>; - const purpleAiRules = <%- JSON.stringify(purpleAi.rules) %>; + const oobeeAiHtmlETL = <%- oobeeAi.htmlETL %>; + const oobeeAiRules = <%- JSON.stringify(oobeeAi.rules) %>; // extract tagname and attribute name from html tag // e.g. ["input", "type", "value", "role"] from @@ -217,14 +217,14 @@ const api = memoizeApiCall(); const apiUrls = { - catalog: 'https://govtechsg.github.io/purple-ai/catalog.json', - getRuleIdData: (ruleId) => `https://govtechsg.github.io/purple-ai/results/${ruleId}.json` + catalog: 'https://govtechsg.github.io/oobee-ai/catalog.json', + getRuleIdData: (ruleId) => `https://govtechsg.github.io/oobee-ai/results/${ruleId}.json` } const isOffline = () => !window.navigator.onLine; const checkPurpleAiQueryLabel = async (ruleId, ruleHtml) => { - const purpleAiQueryLabel = { + const oobeeAiQueryLabel = { label: null, hasNetworkError: false, hasGenericError: false @@ -233,7 +233,7 @@ return api(apiUrls.catalog).then(catalogData => { // no information for current rule if (!catalogData[ruleId] || catalogData[ruleId].length === 0) { - return purpleAiQueryLabel; + return oobeeAiQueryLabel; } if (rulesUsingRoles.includes(ruleId)) { @@ -244,18 +244,18 @@ if (roleForHtml) { const currentLabel = `${htmlElement}_${roleForHtml}`.trim(); const foundLabel = catalogData[ruleId].find(label => label === currentLabel); - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; + return oobeeAiQueryLabel; } } // e.g. li_aria-controls_aria-selected_role - const currentLabelList = getHtmlTagAndAttributes(purpleAiHtmlETL(ruleHtml)); + const currentLabelList = getHtmlTagAndAttributes(oobeeAiHtmlETL(ruleHtml)); const currentLabel = currentLabelList.join('_'); if (catalogData[ruleId].includes(currentLabel)) { - purpleAiQueryLabel.label = escapeHtmlForAI(currentLabel); - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = escapeHtmlForAI(currentLabel); + return oobeeAiQueryLabel; } // count the number of elements in keyArr that @@ -269,8 +269,8 @@ return attrMatch.length >= 3; }) - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; + return oobeeAiQueryLabel; }) .catch(err => { console.error(`An error has occurred while checking if ${ruleId} needs AI query`); @@ -291,8 +291,8 @@ } const handleOfflinePurpleAi = async (ruleId, accordionDiv, html, buttonsDiv, aiErrorDiv) => { - let purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); - if (purpleAiQueryLabel.hasNetworkError) { + let oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); + if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -300,7 +300,7 @@ `This feature requires internet connection. Please try again`, ), ); - } else if (purpleAiQueryLabel.hasNetworkError) { + } else if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -308,10 +308,10 @@ `Something went wrong. Please try again`, ), ); - } else if (!purpleAiQueryLabel.label) { + } else if (!oobeeAiQueryLabel.label) { document.getElementById(accordionDiv).innerHTML = `Processing AI suggestions, please check back later.` } else { - await getPurpleAiAnswer(ruleId, accordionDiv, purpleAiQueryLabel.label, buttonsDiv, aiErrorDiv); + await getPurpleAiAnswer(ruleId, accordionDiv, oobeeAiQueryLabel.label, buttonsDiv, aiErrorDiv); } } diff --git a/src/static/ejs/partials/summaryHeader.ejs b/src/static/ejs/partials/summaryHeader.ejs index 73ab433a..f1e9b80b 100644 --- a/src/static/ejs/partials/summaryHeader.ejs +++ b/src/static/ejs/partials/summaryHeader.ejs @@ -46,7 +46,7 @@ /> - Purple A11y Scan Summary + Oobee Scan Summary <%# diff --git a/src/static/ejs/partials/summaryMain.ejs b/src/static/ejs/partials/summaryMain.ejs index f2f99c23..c8620ac8 100644 --- a/src/static/ejs/partials/summaryMain.ejs +++ b/src/static/ejs/partials/summaryMain.ejs @@ -63,7 +63,7 @@ (Conformance Level A & AA) Success Criteria can be automatically checked so manual testing diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index 6169f39c..c41a5039 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -251,7 +251,7 @@ itemsElement.innerHTML = itemsContent; var phAppVersionElement = document.getElementById('phAppVersion'); - var versionContent = 'Oobee Desktop Version ' + scanData.phAppVersion; + var versionContent = 'Oobee Version ' + scanData.phAppVersion; phAppVersionElement.innerHTML = versionContent; var isCustomFlow = scanData.isCustomFlow; diff --git a/src/static/ejs/summary.ejs b/src/static/ejs/summary.ejs index 6757a79b..472dc8ab 100644 --- a/src/static/ejs/summary.ejs +++ b/src/static/ejs/summary.ejs @@ -3,7 +3,7 @@ - Purple A11y Scan Summary + Oobee Scan Summary - + IMPACT @@ -1594,7 +1594,7 @@
package.json
npm init
npm pkg set type="module"
npm install cypress @govtechsg/purple-hats --save-dev
npm install cypress @govtechsg/oobee --save-dev
node_modules/@govtechsg/purple-hats
npm install
npm run build
node_modules/@govtechsg/oobee
npm i Create cypress.config.js with the following contents, and change your Name, E-mail address, and boolean value for whether rule items requiring manual review in the report should be displayed below: import { defineConfig } from "cypress"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; // viewport used in tests to optimise screenshots const viewportSettings = { width: 1920, height: 1040 }; @@ -174,9 +174,9 @@ Create cypress.config.js with the following contents, and change yo // additional information to include in the "Scan About" section of the report const scanAboutMetadata = { browser: 'Chrome (Desktop)' }; // name of the generated zip of the results at the end of scan - const resultsZipName = "a11y-scan-results" + const resultsZipName = "oobee-scan-results" - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Cypress Scan", // label for test "Your Name", @@ -196,20 +196,20 @@ Create cypress.config.js with the following contents, and change yo setupNodeEvents(on, _config) { on("task", { getPurpleA11yScripts() { - return purpleA11y.getScripts(); + return oobeeA11y.getScripts(); }, async pushPurpleA11yScanResults({res, metadata, elementsToClick}) { - return await purpleA11y.pushScanResults(res, metadata, elementsToClick); + return await oobeeA11y.pushScanResults(res, metadata, elementsToClick); }, returnResultsDir() { - return `results/${purpleA11y.randomToken}_${purpleA11y.scanDetails.urlsCrawled.scanned.length}pages/report.html`; + return `results/${oobeeA11y.randomToken}_${oobeeA11y.scanDetails.urlsCrawled.scanned.length}pages/report.html`; }, finishPurpleA11yTestCase() { - purpleA11y.testThresholds(); + oobeeA11y.testThresholds(); return null; }, async terminatePurpleA11y() { - return await purpleA11y.terminate(); + return await oobeeA11y.terminate(); }, }); }, @@ -231,7 +231,7 @@ Create a sub-folder and file cypress/support/e2e.js with the follow const { elementsToScan, elementsToClick, metadata } = items; const res = await win.runA11yScan(elementsToScan); cy.task("pushPurpleA11yScanResults", {res, metadata, elementsToClick}).then((count) => { return count }); - cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }); }); @@ -242,9 +242,9 @@ Create a sub-folder and file cypress/support/e2e.js with the follow Create cypress/e2e/spec.cy.js with the following contents: describe("template spec", () => { - it("should run purple A11y", () => { + it("should run oobee A11y", () => { cy.visit( - "https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm" + "https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm" ); cy.injectPurpleA11yScripts(); cy.runPurpleA11yScan(); @@ -261,7 +261,7 @@ Create cypress/e2e/spec.cy.js with the following contents: }); Run your test with npx cypress run. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -284,9 +284,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install cypress @types/cypress @govtechsg/purple-hats typescript --save-dev +Install the following node dependencies by running npm install cypress @types/cypress @govtechsg/oobee typescript --save-dev Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -302,9 +303,9 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. @@ -312,7 +313,7 @@ Navigate to node_modules/@govtechsg/purple-hats and run npm i Create cypress.config.ts with the following contents, and change your Name, E-mail address, and boolean value for whether rule items requiring manual review in the report should be displayed below: import { defineConfig } from "cypress"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; interface ViewportSettings { width: number; @@ -335,9 +336,9 @@ Create cypress.config.ts with the following contents, and change yo // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; // name of the generated zip of the results at the end of scan - const resultsZipName: string = "a11y-scan-results" + const resultsZipName: string = "oobee-scan-results" - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Cypress Scan", // label for test "Your Name", @@ -357,20 +358,20 @@ Create cypress.config.ts with the following contents, and change yo setupNodeEvents(on, _config) { on("task", { getPurpleA11yScripts(): string { - return purpleA11y.getScripts(); + return oobeeA11y.getScripts(); }, async pushPurpleA11yScanResults({res, metadata, elementsToClick}: { res: any, metadata: any, elementsToClick: any[] }): Promise<{ mustFix: number, goodToFix: number }> { - return await purpleA11y.pushScanResults(res, metadata, elementsToClick); + return await oobeeA11y.pushScanResults(res, metadata, elementsToClick); }, returnResultsDir(): string { - return `results/${purpleA11y.randomToken}_${purpleA11y.scanDetails.urlsCrawled.scanned.length}pages/reports/report.html`; + return `results/${oobeeA11y.randomToken}_${oobeeA11y.scanDetails.urlsCrawled.scanned.length}pages/reports/report.html`; }, finishPurpleA11yTestCase(): null { - purpleA11y.testThresholds(); + oobeeA11y.testThresholds(); return null; }, async terminatePurpleA11y(): Promise { - return await purpleA11y.terminate(); + return await oobeeA11y.terminate(); }, }); }, @@ -394,7 +395,7 @@ Create a sub-folder and file src/cypress/support/e2e.ts with the fo const { elementsToScan, elementsToClick, metadata } = items; const res = await win.runA11yScan(elementsToScan); cy.task("pushPurpleA11yScanResults", {res, metadata, elementsToClick}).then((count) => { return count }); - cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }); }); @@ -405,9 +406,9 @@ Create a sub-folder and file src/cypress/support/e2e.ts with the fo Create src/cypress/e2e/spec.cy.ts with the following contents: describe("template spec", () => { - it("should run purple A11y", () => { + it("should run oobee A11y", () => { cy.visit( - "https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm" + "https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm" ); cy.injectPurpleA11yScripts(); cy.runPurpleA11yScan(); @@ -424,6 +425,7 @@ Create src/cypress/e2e/spec.cy.ts with the following contents: }); Create cypress.d.ts in the root directory with the following contents: + ``` declare namespace Cypress { interface Chainable { @@ -447,7 +449,7 @@ interface Window { Compile your typescript code with npx tsc. Run your test with npx cypress run. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -460,19 +462,19 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee --save-dev and npx playwright install -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -On your project's root folder, create a Playwright test file purpleA11y-playwright-demo.js: +On your project's root folder, create a Playwright test file oobeeA11y-playwright-demo.js: import { chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; // viewport used in tests to optimise screenshots const viewportSettings = { width: 1920, height: 1040 }; @@ -481,7 +483,7 @@ On your project's root folder, create a Playwright test file purpleA11y-pl // additional information to include in the "Scan About" section of the report const scanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -504,12 +506,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -520,12 +522,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); -Run your test with node purpleA11y-playwright-demo.js . +Run your test with node oobeeA11y-playwright-demo.js . -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -535,9 +537,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats typescript --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee typescript --save-dev and npx playwright install Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -552,17 +555,17 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -Create a sub-folder and Playwright test file src/purpleA11y-playwright-demo.ts with the following contents: +Create a sub-folder and Playwright test file src/oobeeA11y-playwright-demo.ts with the following contents: import { Browser, BrowserContext, Page, chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; declare const runA11yScan: (elementsToScan?: string[]) => Promise; @@ -587,7 +590,7 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -610,12 +613,12 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -777,6 +780,6 @@ You will see Purple A11y results generated in results folder. }); }; - runScript(); + runScript(); diff --git a/README.md b/README.md index 4bcc2aef..57625f0b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# Purple A11y +# Oobee -[Purple A11y](https://go.gov.sg/purple-a11y-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). - -This is the engine and command-line interface (CLI) for Purple A11y. For a desktop graphical user interface (GUI), check out [Purple A11y Desktop](https://go.gov.sg/purple-a11y). The official application can only be downloaded at [https://go.gov.sg/purple-a11y-cicd](https://go.gov.sg/purple-a11y-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. +[Oobee](https://go.gov.sg/oobee-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). +This is the engine and command-line interface (CLI) for Oobee. For a desktop graphical user interface (GUI), check out [Oobee Desktop](https://go.gov.sg/oobee). The official application can only be downloaded at [https://go.gov.sg/oobee-cicd](https://go.gov.sg/oobee-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. ## Technology Stack @@ -15,27 +14,31 @@ This is the engine and command-line interface (CLI) for Purple A11y. For a desk 6. [Corretto](https://aws.amazon.com/corretto) 7. [VeraPDF](https://github.com/veraPDF/veraPDF-apps) -## Using Purple A11y as a NodeJS module +## Using Oobee as a NodeJS module -If you wish to use Purple A11y as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. +If you wish to use Oobee as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. ## Prerequisites and Installations -### Portable Purple A11y +### Portable Oobee -Portable Purple A11y is the recommended way to run Purple A11y as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Purple A11y. +Portable Oobee is the recommended way to run Oobee as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Oobee. ### Manual Installation Please ensure the following requirements are met: #### Node.js + - A Node distribution of 20 (LTS) or above. - To check your version of Node, go into terminal and paste the command bellow + ```shell node -v ``` -- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + +- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + ```shell # Install NodeJS version with NVM nvm install --lts @@ -43,20 +46,26 @@ nvm install --lts # For subsequent use, you will need to run the command below each time you open a new terminal nvm use --lts ``` + - Install the required NPM packages with `npm install`. - Build the project with `npm run build` before you try to run it with `npm start`. #### Java JRE/JDK + - A JRE/JDK distribution of version 11 or above. - To check your version of Java, go into terminal and paste the command bellow + ```shell java --version ``` + - If you do not have java, you can consider installing [Corretto](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html) distribution of OpenJDK. #### VeraPDF -- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. + +- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. - Ensure you have VeraPDF set in PATH then verify verapdf is installed correctly: + ```shell # Invoke the VeraPDF installer # Windows users should use vera-install.bat instead of vera-install @@ -77,22 +86,22 @@ Please refer to [Troubleshooting section](#troubleshooting) for more information ## Features -Purple A11y can perform the following to scan the target URL. +Oobee can perform the following to scan the target URL. -- To **run** Purple A11y in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. +- To **run** Oobee in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. - Results will be compiled in JSON format, followed by generating a HTML report. > NOTE: For your initial scan, there may be some loading time required before use. Purple-A11y will also ask for your name and email address and collect your app usage data to personalise your experience. Your information fully complies with [GovTech’s Privacy Policy](https://www.tech.gov.sg/privacy/). #### Delete/Edit Details + > You may delete and edit your cached name and e-mail address by running the following command to delete `userData.txt`: -> - Windows (PowerShell): `rm "$env:APPDATA\Purple A11y\userData.txt"` -> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Purple A11y/userData.txt"` +> - Windows (PowerShell): `rm "$env:APPDATA\Oobee\userData.txt"` +> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Oobee/userData.txt"` If `userData.txt` does not exists just run `npm start`. - ### Scan Selection You can interact via your arrow keys. @@ -100,7 +109,7 @@ You can interact via your arrow keys. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience.│ │ │ │ Welcome back User! │ @@ -119,14 +128,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? (Y/n) No +? Do you want oobee to run in the background? (Y/n) No ``` ### Sitemap Scan @@ -134,14 +143,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL or file path to sitemap, or drag and drop a sitemap file here: https://www.sitemaps.org/sitemap.xml @@ -154,7 +163,7 @@ Headless mode would allow you to run the scan in the background. If you would li Scanning website... -#purple-a11y will then start scraping from the file link provided above. +#oobee will then start scraping from the file link provided above. #Console results ``` @@ -170,14 +179,14 @@ If the sitemap URL provided is invalid, an error message will be prompted for yo ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? Yes +? Do you want oobee to run in the background? Yes ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL of website: https://www.domain.org @@ -191,19 +200,19 @@ If the website URL provided is invalid, an error message will be prompted for yo ### Customised Mobile Device Scan -``` shell +```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) (Use arrow keys) -❯ Desktop +❯ Desktop Mobile Custom ``` @@ -212,14 +221,14 @@ Choose `Mobile` for a default mobile screen size scan and `Custom` to choose a d ### Custom flow -Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. +Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. 1. Start by choosing the `Custom flow` in the menu selection. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ @@ -229,10 +238,10 @@ Custom flow allows you to specify a user journey by enabling you to click the sc Sitemap Website ❯ Custom - ``` +``` 1. Specify the URL of the starting page you wish to scan -2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. +2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. 3. You may drag the top black bar to the bottom of the page in the event it prevents you from viewing / blocking certain page elements. 4. Close the Chrome window to end the scan. @@ -240,11 +249,10 @@ Other options: - You can specify sites to exclude from accessibility scan (e.g. login page) by adding a pattern of the domain to `exclusions.txt`. An example of `exclusions.txt`: -``` txt +```txt \.*login.singpass.gov.sg\.* ``` - #### Known Issues If the custom flow fails to start, you might be running multiple versions of Playwright. Re-install Playwright: @@ -259,9 +267,8 @@ npx playwright@1.27.1 install ### CLI Mode -CLI mode is designed to be run in continuous integration (CI) environment. - Run `npm run cli` for a set of command-line parameters available. - +CLI mode is designed to be run in continuous integration (CI) environment. +Run `npm run cli` for a set of command-line parameters available. ```shell Usage: npm run cli -- -c -d -w -If the device name contains ```(``` and ```)```, wrap the device name in single quotes when entered into the CLI. -Please note that ```-d``` and ```-w``` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. +If the device name contains `(` and `)`, wrap the device name in single quotes when entered into the CLI. +Please note that `-d` and `-w` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' +npm run cli -- -c 2 -o oobee-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' ``` If the site you want to scan has a query string wrap the link in single quotes when entered into the CLI. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with a custom screen width '360', run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with a custom screen width '360', run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u "http://localhost:8000" -w 360 +npm run cli -- -c 2 -o oobee-scan-results.zip -u "http://localhost:8000" -w 360 ``` ## Report -Once a scan of the site is completed. + +Once a scan of the site is completed. A report will be downloaded into the current working directory. ## Accessibility Scan Results -Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). +Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). -For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). +For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). ## Troubleshooting @@ -503,12 +511,12 @@ Please refer to the information below to assist in debugging. Most errors below **Issue**: When your Node.js version is incompatible, you may face the following syntax error. - ```shell const URL_NO_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line ^ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@:%\._\+~#=]{0,254}[\p{L}0-9]\.[a-z]{2,63}(:\d{1,5})?(/[-\p{L}0-9@:%_\+.~#?&//=\(\)]*)?/: Invalid escape ``` + **Solution**: Install Node.js versions >= 20, i.e. Node.js v20 and above. ### Compiled against a different Node.js version @@ -516,7 +524,7 @@ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@ **Issue**: When you switch between different versions of Node.js in your environment, you may face the following error. ```shell -/purple-a11y/node_modules/bindings/bindings.js:91 +/oobee/node_modules/bindings/bindings.js:91 throw e ^ @@ -531,15 +539,15 @@ the module (for instance, using `npm rebuild` or `npm install`). ### dyld Error -**Issue**: Not able to run Purple A11y due to the following error shown below +**Issue**: Not able to run Oobee due to the following error shown below ```shell dyld: lazy symbol binding failed: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace dyld: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /PURPLE_A11y/purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /PURPLE_A11y/oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace zsh: abort node index.js @@ -554,7 +562,7 @@ zsh: abort node index.js **Limitation**: Due to animations causing elements to shift out of the viewport after an Axe scan, there's a risk of element screenshots timing out within 5 seconds if the element is not found. This known issue is particularly prevalent in scenarios like carousels with interval-based transitions. -## FAQ +## FAQ ### How do I limit number of pages scanned? @@ -566,9 +574,8 @@ To do this, run CLI mode `npm run cli --` with the needed settings and specify ` We recommend looking at our **Technology Stack** to understand the usage of each component. Take your time to understand. - ## Additional Information on Data -Purple A11y uses third-party open-source tools that may be downloaded over the Internet during the installation process of Purple A11y. Users should be aware of the libraries used by examining `package.json`. +Oobee uses third-party open-source tools that may be downloaded over the Internet during the installation process of Oobee. Users should be aware of the libraries used by examining `package.json`. -Purple A11y may send information to the website, URL and HTML code snippets where the user chooses to initiate a Purple A11y scan for telemetry purposes. +Oobee may send information to the website, URL and HTML code snippets where the user chooses to initiate a Oobee scan for telemetry purposes. diff --git a/__mocks__/mock-report.html b/__mocks__/mock-report.html index b08801be..8ca6ee93 100644 --- a/__mocks__/mock-report.html +++ b/__mocks__/mock-report.html @@ -523,11 +523,11 @@ body.dark .footer { background-color: #272727; } - #a11y-table { + #oobee-table { background-color: #fff; width: 100%; } - body.dark #a11y-table { + body.dark #oobee-table { background-color: #272727; } table.dataTable { @@ -1117,7 +1117,7 @@ Accessibility Report - + IMPACT @@ -1151,7 +1151,7 @@ Accessibility Report @@ -1204,7 +1204,7 @@ Accessibility Report @@ -1257,7 +1257,7 @@ Accessibility Report @@ -1310,7 +1310,7 @@ Accessibility Report @@ -1374,7 +1374,7 @@ Accessibility Report diff --git a/src/static/ejs/partials/scripts/categorySummary.ejs b/src/static/ejs/partials/scripts/categorySummary.ejs index 6545b94a..9a2ff175 100644 --- a/src/static/ejs/partials/scripts/categorySummary.ejs +++ b/src/static/ejs/partials/scripts/categorySummary.ejs @@ -51,8 +51,8 @@ filteredItems[category].rules.forEach((rule, index) => { const buttonAriaLabel = `${rule.description}, ${rule.totalItems} occurrences`; - const purpleAiSvgId = `${category}-${rule.rule}-${index}`; - const isPurpleAiRule = purpleAiRules.includes(rule.rule); + const oobeeAiSvgId = `${category}-${rule.rule}-${index}`; + const isPurpleAiRule = oobeeAiRules.includes(rule.rule); // START new createElementFromString const ruleItem = createElementFromString(` @@ -67,8 +67,8 @@ ${ isPurpleAiRule ? `aria-describedby="containsAISuggestions" - onfocus="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" - onblur="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" + onfocus="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" + onblur="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" onmousedown="event.preventDefault()"` : `` } @@ -83,7 +83,7 @@ ${htmlEscapeString(rule.description)} ${ isPurpleAiRule - ? ` diff --git a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs index 38420722..ef8da4bc 100644 --- a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +++ b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs @@ -97,7 +97,7 @@ category summary is clicked %> `), ); - if (purpleAiRules.includes(selectedRule.rule)) { + if (oobeeAiRules.includes(selectedRule.rule)) { document.querySelector('#expandedRuleAiFeedback').style.display = 'block'; } else { document.querySelector('#expandedRuleAiFeedback').style.display = 'none'; @@ -535,10 +535,10 @@ category summary is clicked %> const buttonDivForAiFeedback = `${buttonAIId}-${index}`; const aiErrorDiv = `${errorAIId}-${index}`; let itemCard; - const isPurpleAiRule = purpleAiRules.includes(ruleInCategory.rule); - let purpleAiQueryLabel; + const isPurpleAiRule = oobeeAiRules.includes(ruleInCategory.rule); + let oobeeAiQueryLabel; if (isPurpleAiRule) { - purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); + oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); } itemCard = createElementFromString(` @@ -621,7 +621,7 @@ category summary is clicked %> AI suggestion - ${purpleAiQueryLabel.hasNetworkError ? + ${oobeeAiQueryLabel.hasNetworkError ? ` Generate response ` : - (purpleAiQueryLabel.label ? + (oobeeAiQueryLabel.label ? ` diff --git a/src/static/ejs/partials/scripts/utils.ejs b/src/static/ejs/partials/scripts/utils.ejs index 9c4b18f7..3b573640 100644 --- a/src/static/ejs/partials/scripts/utils.ejs +++ b/src/static/ejs/partials/scripts/utils.ejs @@ -6,8 +6,8 @@ return tempContainer.firstChild; } - const purpleAiHtmlETL = <%- purpleAi.htmlETL %>; - const purpleAiRules = <%- JSON.stringify(purpleAi.rules) %>; + const oobeeAiHtmlETL = <%- oobeeAi.htmlETL %>; + const oobeeAiRules = <%- JSON.stringify(oobeeAi.rules) %>; // extract tagname and attribute name from html tag // e.g. ["input", "type", "value", "role"] from @@ -217,14 +217,14 @@ const api = memoizeApiCall(); const apiUrls = { - catalog: 'https://govtechsg.github.io/purple-ai/catalog.json', - getRuleIdData: (ruleId) => `https://govtechsg.github.io/purple-ai/results/${ruleId}.json` + catalog: 'https://govtechsg.github.io/oobee-ai/catalog.json', + getRuleIdData: (ruleId) => `https://govtechsg.github.io/oobee-ai/results/${ruleId}.json` } const isOffline = () => !window.navigator.onLine; const checkPurpleAiQueryLabel = async (ruleId, ruleHtml) => { - const purpleAiQueryLabel = { + const oobeeAiQueryLabel = { label: null, hasNetworkError: false, hasGenericError: false @@ -233,7 +233,7 @@ return api(apiUrls.catalog).then(catalogData => { // no information for current rule if (!catalogData[ruleId] || catalogData[ruleId].length === 0) { - return purpleAiQueryLabel; + return oobeeAiQueryLabel; } if (rulesUsingRoles.includes(ruleId)) { @@ -244,18 +244,18 @@ if (roleForHtml) { const currentLabel = `${htmlElement}_${roleForHtml}`.trim(); const foundLabel = catalogData[ruleId].find(label => label === currentLabel); - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; + return oobeeAiQueryLabel; } } // e.g. li_aria-controls_aria-selected_role - const currentLabelList = getHtmlTagAndAttributes(purpleAiHtmlETL(ruleHtml)); + const currentLabelList = getHtmlTagAndAttributes(oobeeAiHtmlETL(ruleHtml)); const currentLabel = currentLabelList.join('_'); if (catalogData[ruleId].includes(currentLabel)) { - purpleAiQueryLabel.label = escapeHtmlForAI(currentLabel); - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = escapeHtmlForAI(currentLabel); + return oobeeAiQueryLabel; } // count the number of elements in keyArr that @@ -269,8 +269,8 @@ return attrMatch.length >= 3; }) - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; + return oobeeAiQueryLabel; }) .catch(err => { console.error(`An error has occurred while checking if ${ruleId} needs AI query`); @@ -291,8 +291,8 @@ } const handleOfflinePurpleAi = async (ruleId, accordionDiv, html, buttonsDiv, aiErrorDiv) => { - let purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); - if (purpleAiQueryLabel.hasNetworkError) { + let oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); + if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -300,7 +300,7 @@ `This feature requires internet connection. Please try again`, ), ); - } else if (purpleAiQueryLabel.hasNetworkError) { + } else if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -308,10 +308,10 @@ `Something went wrong. Please try again`, ), ); - } else if (!purpleAiQueryLabel.label) { + } else if (!oobeeAiQueryLabel.label) { document.getElementById(accordionDiv).innerHTML = `Processing AI suggestions, please check back later.` } else { - await getPurpleAiAnswer(ruleId, accordionDiv, purpleAiQueryLabel.label, buttonsDiv, aiErrorDiv); + await getPurpleAiAnswer(ruleId, accordionDiv, oobeeAiQueryLabel.label, buttonsDiv, aiErrorDiv); } } diff --git a/src/static/ejs/partials/summaryHeader.ejs b/src/static/ejs/partials/summaryHeader.ejs index 73ab433a..f1e9b80b 100644 --- a/src/static/ejs/partials/summaryHeader.ejs +++ b/src/static/ejs/partials/summaryHeader.ejs @@ -46,7 +46,7 @@ /> - Purple A11y Scan Summary + Oobee Scan Summary <%# diff --git a/src/static/ejs/partials/summaryMain.ejs b/src/static/ejs/partials/summaryMain.ejs index f2f99c23..c8620ac8 100644 --- a/src/static/ejs/partials/summaryMain.ejs +++ b/src/static/ejs/partials/summaryMain.ejs @@ -63,7 +63,7 @@ (Conformance Level A & AA) Success Criteria can be automatically checked so manual testing diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index 6169f39c..c41a5039 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -251,7 +251,7 @@ itemsElement.innerHTML = itemsContent; var phAppVersionElement = document.getElementById('phAppVersion'); - var versionContent = 'Oobee Desktop Version ' + scanData.phAppVersion; + var versionContent = 'Oobee Version ' + scanData.phAppVersion; phAppVersionElement.innerHTML = versionContent; var isCustomFlow = scanData.isCustomFlow; diff --git a/src/static/ejs/summary.ejs b/src/static/ejs/summary.ejs index 6757a79b..472dc8ab 100644 --- a/src/static/ejs/summary.ejs +++ b/src/static/ejs/summary.ejs @@ -3,7 +3,7 @@ - Purple A11y Scan Summary + Oobee Scan Summary - + IMPACT @@ -1594,7 +1594,7 @@
cypress.config.js
cypress/support/e2e.js
cypress/e2e/spec.cy.js
npx cypress run
results
npm install cypress @types/cypress @govtechsg/purple-hats typescript --save-dev
npm install cypress @types/cypress @govtechsg/oobee typescript --save-dev
tsconfig.json
npm i Create cypress.config.ts with the following contents, and change your Name, E-mail address, and boolean value for whether rule items requiring manual review in the report should be displayed below: import { defineConfig } from "cypress"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; interface ViewportSettings { width: number; @@ -335,9 +336,9 @@ Create cypress.config.ts with the following contents, and change yo // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; // name of the generated zip of the results at the end of scan - const resultsZipName: string = "a11y-scan-results" + const resultsZipName: string = "oobee-scan-results" - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Cypress Scan", // label for test "Your Name", @@ -357,20 +358,20 @@ Create cypress.config.ts with the following contents, and change yo setupNodeEvents(on, _config) { on("task", { getPurpleA11yScripts(): string { - return purpleA11y.getScripts(); + return oobeeA11y.getScripts(); }, async pushPurpleA11yScanResults({res, metadata, elementsToClick}: { res: any, metadata: any, elementsToClick: any[] }): Promise<{ mustFix: number, goodToFix: number }> { - return await purpleA11y.pushScanResults(res, metadata, elementsToClick); + return await oobeeA11y.pushScanResults(res, metadata, elementsToClick); }, returnResultsDir(): string { - return `results/${purpleA11y.randomToken}_${purpleA11y.scanDetails.urlsCrawled.scanned.length}pages/reports/report.html`; + return `results/${oobeeA11y.randomToken}_${oobeeA11y.scanDetails.urlsCrawled.scanned.length}pages/reports/report.html`; }, finishPurpleA11yTestCase(): null { - purpleA11y.testThresholds(); + oobeeA11y.testThresholds(); return null; }, async terminatePurpleA11y(): Promise { - return await purpleA11y.terminate(); + return await oobeeA11y.terminate(); }, }); }, @@ -394,7 +395,7 @@ Create a sub-folder and file src/cypress/support/e2e.ts with the fo const { elementsToScan, elementsToClick, metadata } = items; const res = await win.runA11yScan(elementsToScan); cy.task("pushPurpleA11yScanResults", {res, metadata, elementsToClick}).then((count) => { return count }); - cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + cy.task("finishPurpleA11yTestCase"); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }); }); @@ -405,9 +406,9 @@ Create a sub-folder and file src/cypress/support/e2e.ts with the fo Create src/cypress/e2e/spec.cy.ts with the following contents: describe("template spec", () => { - it("should run purple A11y", () => { + it("should run oobee A11y", () => { cy.visit( - "https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm" + "https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm" ); cy.injectPurpleA11yScripts(); cy.runPurpleA11yScan(); @@ -424,6 +425,7 @@ Create src/cypress/e2e/spec.cy.ts with the following contents: }); Create cypress.d.ts in the root directory with the following contents: + ``` declare namespace Cypress { interface Chainable { @@ -447,7 +449,7 @@ interface Window { Compile your typescript code with npx tsc. Run your test with npx cypress run. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder.
cypress.config.ts
src/cypress/support/e2e.ts
src/cypress/e2e/spec.cy.ts
cypress.d.ts
npx tsc
npm install playwright @govtechsg/purple-hats --save-dev
npx playwright install
npm install playwright @govtechsg/oobee --save-dev
purpleA11y-playwright-demo.js
oobeeA11y-playwright-demo.js
purpleA11y-pl // additional information to include in the "Scan About" section of the report const scanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -504,12 +506,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -520,12 +522,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); -Run your test with node purpleA11y-playwright-demo.js . +Run your test with node oobeeA11y-playwright-demo.js . -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -535,9 +537,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats typescript --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee typescript --save-dev and npx playwright install Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -552,17 +555,17 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -Create a sub-folder and Playwright test file src/purpleA11y-playwright-demo.ts with the following contents: +Create a sub-folder and Playwright test file src/oobeeA11y-playwright-demo.ts with the following contents: import { Browser, BrowserContext, Page, chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; declare const runA11yScan: (elementsToScan?: string[]) => Promise; @@ -587,7 +590,7 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -610,12 +613,12 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -777,6 +780,6 @@ You will see Purple A11y results generated in results folder. }); }; - runScript(); + runScript(); diff --git a/README.md b/README.md index 4bcc2aef..57625f0b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# Purple A11y +# Oobee -[Purple A11y](https://go.gov.sg/purple-a11y-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). - -This is the engine and command-line interface (CLI) for Purple A11y. For a desktop graphical user interface (GUI), check out [Purple A11y Desktop](https://go.gov.sg/purple-a11y). The official application can only be downloaded at [https://go.gov.sg/purple-a11y-cicd](https://go.gov.sg/purple-a11y-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. +[Oobee](https://go.gov.sg/oobee-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). +This is the engine and command-line interface (CLI) for Oobee. For a desktop graphical user interface (GUI), check out [Oobee Desktop](https://go.gov.sg/oobee). The official application can only be downloaded at [https://go.gov.sg/oobee-cicd](https://go.gov.sg/oobee-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. ## Technology Stack @@ -15,27 +14,31 @@ This is the engine and command-line interface (CLI) for Purple A11y. For a desk 6. [Corretto](https://aws.amazon.com/corretto) 7. [VeraPDF](https://github.com/veraPDF/veraPDF-apps) -## Using Purple A11y as a NodeJS module +## Using Oobee as a NodeJS module -If you wish to use Purple A11y as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. +If you wish to use Oobee as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. ## Prerequisites and Installations -### Portable Purple A11y +### Portable Oobee -Portable Purple A11y is the recommended way to run Purple A11y as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Purple A11y. +Portable Oobee is the recommended way to run Oobee as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Oobee. ### Manual Installation Please ensure the following requirements are met: #### Node.js + - A Node distribution of 20 (LTS) or above. - To check your version of Node, go into terminal and paste the command bellow + ```shell node -v ``` -- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + +- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + ```shell # Install NodeJS version with NVM nvm install --lts @@ -43,20 +46,26 @@ nvm install --lts # For subsequent use, you will need to run the command below each time you open a new terminal nvm use --lts ``` + - Install the required NPM packages with `npm install`. - Build the project with `npm run build` before you try to run it with `npm start`. #### Java JRE/JDK + - A JRE/JDK distribution of version 11 or above. - To check your version of Java, go into terminal and paste the command bellow + ```shell java --version ``` + - If you do not have java, you can consider installing [Corretto](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html) distribution of OpenJDK. #### VeraPDF -- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. + +- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. - Ensure you have VeraPDF set in PATH then verify verapdf is installed correctly: + ```shell # Invoke the VeraPDF installer # Windows users should use vera-install.bat instead of vera-install @@ -77,22 +86,22 @@ Please refer to [Troubleshooting section](#troubleshooting) for more information ## Features -Purple A11y can perform the following to scan the target URL. +Oobee can perform the following to scan the target URL. -- To **run** Purple A11y in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. +- To **run** Oobee in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. - Results will be compiled in JSON format, followed by generating a HTML report. > NOTE: For your initial scan, there may be some loading time required before use. Purple-A11y will also ask for your name and email address and collect your app usage data to personalise your experience. Your information fully complies with [GovTech’s Privacy Policy](https://www.tech.gov.sg/privacy/). #### Delete/Edit Details + > You may delete and edit your cached name and e-mail address by running the following command to delete `userData.txt`: -> - Windows (PowerShell): `rm "$env:APPDATA\Purple A11y\userData.txt"` -> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Purple A11y/userData.txt"` +> - Windows (PowerShell): `rm "$env:APPDATA\Oobee\userData.txt"` +> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Oobee/userData.txt"` If `userData.txt` does not exists just run `npm start`. - ### Scan Selection You can interact via your arrow keys. @@ -100,7 +109,7 @@ You can interact via your arrow keys. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience.│ │ │ │ Welcome back User! │ @@ -119,14 +128,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? (Y/n) No +? Do you want oobee to run in the background? (Y/n) No ``` ### Sitemap Scan @@ -134,14 +143,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL or file path to sitemap, or drag and drop a sitemap file here: https://www.sitemaps.org/sitemap.xml @@ -154,7 +163,7 @@ Headless mode would allow you to run the scan in the background. If you would li Scanning website... -#purple-a11y will then start scraping from the file link provided above. +#oobee will then start scraping from the file link provided above. #Console results ``` @@ -170,14 +179,14 @@ If the sitemap URL provided is invalid, an error message will be prompted for yo ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? Yes +? Do you want oobee to run in the background? Yes ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL of website: https://www.domain.org @@ -191,19 +200,19 @@ If the website URL provided is invalid, an error message will be prompted for yo ### Customised Mobile Device Scan -``` shell +```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) (Use arrow keys) -❯ Desktop +❯ Desktop Mobile Custom ``` @@ -212,14 +221,14 @@ Choose `Mobile` for a default mobile screen size scan and `Custom` to choose a d ### Custom flow -Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. +Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. 1. Start by choosing the `Custom flow` in the menu selection. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ @@ -229,10 +238,10 @@ Custom flow allows you to specify a user journey by enabling you to click the sc Sitemap Website ❯ Custom - ``` +``` 1. Specify the URL of the starting page you wish to scan -2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. +2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. 3. You may drag the top black bar to the bottom of the page in the event it prevents you from viewing / blocking certain page elements. 4. Close the Chrome window to end the scan. @@ -240,11 +249,10 @@ Other options: - You can specify sites to exclude from accessibility scan (e.g. login page) by adding a pattern of the domain to `exclusions.txt`. An example of `exclusions.txt`: -``` txt +```txt \.*login.singpass.gov.sg\.* ``` - #### Known Issues If the custom flow fails to start, you might be running multiple versions of Playwright. Re-install Playwright: @@ -259,9 +267,8 @@ npx playwright@1.27.1 install ### CLI Mode -CLI mode is designed to be run in continuous integration (CI) environment. - Run `npm run cli` for a set of command-line parameters available. - +CLI mode is designed to be run in continuous integration (CI) environment. +Run `npm run cli` for a set of command-line parameters available. ```shell Usage: npm run cli -- -c -d -w -If the device name contains ```(``` and ```)```, wrap the device name in single quotes when entered into the CLI. -Please note that ```-d``` and ```-w``` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. +If the device name contains `(` and `)`, wrap the device name in single quotes when entered into the CLI. +Please note that `-d` and `-w` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' +npm run cli -- -c 2 -o oobee-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' ``` If the site you want to scan has a query string wrap the link in single quotes when entered into the CLI. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with a custom screen width '360', run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with a custom screen width '360', run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u "http://localhost:8000" -w 360 +npm run cli -- -c 2 -o oobee-scan-results.zip -u "http://localhost:8000" -w 360 ``` ## Report -Once a scan of the site is completed. + +Once a scan of the site is completed. A report will be downloaded into the current working directory. ## Accessibility Scan Results -Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). +Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). -For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). +For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). ## Troubleshooting @@ -503,12 +511,12 @@ Please refer to the information below to assist in debugging. Most errors below **Issue**: When your Node.js version is incompatible, you may face the following syntax error. - ```shell const URL_NO_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line ^ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@:%\._\+~#=]{0,254}[\p{L}0-9]\.[a-z]{2,63}(:\d{1,5})?(/[-\p{L}0-9@:%_\+.~#?&//=\(\)]*)?/: Invalid escape ``` + **Solution**: Install Node.js versions >= 20, i.e. Node.js v20 and above. ### Compiled against a different Node.js version @@ -516,7 +524,7 @@ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@ **Issue**: When you switch between different versions of Node.js in your environment, you may face the following error. ```shell -/purple-a11y/node_modules/bindings/bindings.js:91 +/oobee/node_modules/bindings/bindings.js:91 throw e ^ @@ -531,15 +539,15 @@ the module (for instance, using `npm rebuild` or `npm install`). ### dyld Error -**Issue**: Not able to run Purple A11y due to the following error shown below +**Issue**: Not able to run Oobee due to the following error shown below ```shell dyld: lazy symbol binding failed: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace dyld: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /PURPLE_A11y/purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /PURPLE_A11y/oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace zsh: abort node index.js @@ -554,7 +562,7 @@ zsh: abort node index.js **Limitation**: Due to animations causing elements to shift out of the viewport after an Axe scan, there's a risk of element screenshots timing out within 5 seconds if the element is not found. This known issue is particularly prevalent in scenarios like carousels with interval-based transitions. -## FAQ +## FAQ ### How do I limit number of pages scanned? @@ -566,9 +574,8 @@ To do this, run CLI mode `npm run cli --` with the needed settings and specify ` We recommend looking at our **Technology Stack** to understand the usage of each component. Take your time to understand. - ## Additional Information on Data -Purple A11y uses third-party open-source tools that may be downloaded over the Internet during the installation process of Purple A11y. Users should be aware of the libraries used by examining `package.json`. +Oobee uses third-party open-source tools that may be downloaded over the Internet during the installation process of Oobee. Users should be aware of the libraries used by examining `package.json`. -Purple A11y may send information to the website, URL and HTML code snippets where the user chooses to initiate a Purple A11y scan for telemetry purposes. +Oobee may send information to the website, URL and HTML code snippets where the user chooses to initiate a Oobee scan for telemetry purposes. diff --git a/__mocks__/mock-report.html b/__mocks__/mock-report.html index b08801be..8ca6ee93 100644 --- a/__mocks__/mock-report.html +++ b/__mocks__/mock-report.html @@ -523,11 +523,11 @@ body.dark .footer { background-color: #272727; } - #a11y-table { + #oobee-table { background-color: #fff; width: 100%; } - body.dark #a11y-table { + body.dark #oobee-table { background-color: #272727; } table.dataTable { @@ -1117,7 +1117,7 @@ Accessibility Report - + IMPACT @@ -1151,7 +1151,7 @@ Accessibility Report @@ -1204,7 +1204,7 @@ Accessibility Report @@ -1257,7 +1257,7 @@ Accessibility Report @@ -1310,7 +1310,7 @@ Accessibility Report @@ -1374,7 +1374,7 @@ Accessibility Report diff --git a/src/static/ejs/partials/scripts/categorySummary.ejs b/src/static/ejs/partials/scripts/categorySummary.ejs index 6545b94a..9a2ff175 100644 --- a/src/static/ejs/partials/scripts/categorySummary.ejs +++ b/src/static/ejs/partials/scripts/categorySummary.ejs @@ -51,8 +51,8 @@ filteredItems[category].rules.forEach((rule, index) => { const buttonAriaLabel = `${rule.description}, ${rule.totalItems} occurrences`; - const purpleAiSvgId = `${category}-${rule.rule}-${index}`; - const isPurpleAiRule = purpleAiRules.includes(rule.rule); + const oobeeAiSvgId = `${category}-${rule.rule}-${index}`; + const isPurpleAiRule = oobeeAiRules.includes(rule.rule); // START new createElementFromString const ruleItem = createElementFromString(` @@ -67,8 +67,8 @@ ${ isPurpleAiRule ? `aria-describedby="containsAISuggestions" - onfocus="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" - onblur="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" + onfocus="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" + onblur="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" onmousedown="event.preventDefault()"` : `` } @@ -83,7 +83,7 @@ ${htmlEscapeString(rule.description)} ${ isPurpleAiRule - ? ` diff --git a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs index 38420722..ef8da4bc 100644 --- a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +++ b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs @@ -97,7 +97,7 @@ category summary is clicked %> `), ); - if (purpleAiRules.includes(selectedRule.rule)) { + if (oobeeAiRules.includes(selectedRule.rule)) { document.querySelector('#expandedRuleAiFeedback').style.display = 'block'; } else { document.querySelector('#expandedRuleAiFeedback').style.display = 'none'; @@ -535,10 +535,10 @@ category summary is clicked %> const buttonDivForAiFeedback = `${buttonAIId}-${index}`; const aiErrorDiv = `${errorAIId}-${index}`; let itemCard; - const isPurpleAiRule = purpleAiRules.includes(ruleInCategory.rule); - let purpleAiQueryLabel; + const isPurpleAiRule = oobeeAiRules.includes(ruleInCategory.rule); + let oobeeAiQueryLabel; if (isPurpleAiRule) { - purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); + oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); } itemCard = createElementFromString(` @@ -621,7 +621,7 @@ category summary is clicked %> AI suggestion - ${purpleAiQueryLabel.hasNetworkError ? + ${oobeeAiQueryLabel.hasNetworkError ? ` Generate response ` : - (purpleAiQueryLabel.label ? + (oobeeAiQueryLabel.label ? ` diff --git a/src/static/ejs/partials/scripts/utils.ejs b/src/static/ejs/partials/scripts/utils.ejs index 9c4b18f7..3b573640 100644 --- a/src/static/ejs/partials/scripts/utils.ejs +++ b/src/static/ejs/partials/scripts/utils.ejs @@ -6,8 +6,8 @@ return tempContainer.firstChild; } - const purpleAiHtmlETL = <%- purpleAi.htmlETL %>; - const purpleAiRules = <%- JSON.stringify(purpleAi.rules) %>; + const oobeeAiHtmlETL = <%- oobeeAi.htmlETL %>; + const oobeeAiRules = <%- JSON.stringify(oobeeAi.rules) %>; // extract tagname and attribute name from html tag // e.g. ["input", "type", "value", "role"] from @@ -217,14 +217,14 @@ const api = memoizeApiCall(); const apiUrls = { - catalog: 'https://govtechsg.github.io/purple-ai/catalog.json', - getRuleIdData: (ruleId) => `https://govtechsg.github.io/purple-ai/results/${ruleId}.json` + catalog: 'https://govtechsg.github.io/oobee-ai/catalog.json', + getRuleIdData: (ruleId) => `https://govtechsg.github.io/oobee-ai/results/${ruleId}.json` } const isOffline = () => !window.navigator.onLine; const checkPurpleAiQueryLabel = async (ruleId, ruleHtml) => { - const purpleAiQueryLabel = { + const oobeeAiQueryLabel = { label: null, hasNetworkError: false, hasGenericError: false @@ -233,7 +233,7 @@ return api(apiUrls.catalog).then(catalogData => { // no information for current rule if (!catalogData[ruleId] || catalogData[ruleId].length === 0) { - return purpleAiQueryLabel; + return oobeeAiQueryLabel; } if (rulesUsingRoles.includes(ruleId)) { @@ -244,18 +244,18 @@ if (roleForHtml) { const currentLabel = `${htmlElement}_${roleForHtml}`.trim(); const foundLabel = catalogData[ruleId].find(label => label === currentLabel); - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; + return oobeeAiQueryLabel; } } // e.g. li_aria-controls_aria-selected_role - const currentLabelList = getHtmlTagAndAttributes(purpleAiHtmlETL(ruleHtml)); + const currentLabelList = getHtmlTagAndAttributes(oobeeAiHtmlETL(ruleHtml)); const currentLabel = currentLabelList.join('_'); if (catalogData[ruleId].includes(currentLabel)) { - purpleAiQueryLabel.label = escapeHtmlForAI(currentLabel); - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = escapeHtmlForAI(currentLabel); + return oobeeAiQueryLabel; } // count the number of elements in keyArr that @@ -269,8 +269,8 @@ return attrMatch.length >= 3; }) - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; + return oobeeAiQueryLabel; }) .catch(err => { console.error(`An error has occurred while checking if ${ruleId} needs AI query`); @@ -291,8 +291,8 @@ } const handleOfflinePurpleAi = async (ruleId, accordionDiv, html, buttonsDiv, aiErrorDiv) => { - let purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); - if (purpleAiQueryLabel.hasNetworkError) { + let oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); + if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -300,7 +300,7 @@ `This feature requires internet connection. Please try again`, ), ); - } else if (purpleAiQueryLabel.hasNetworkError) { + } else if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -308,10 +308,10 @@ `Something went wrong. Please try again`, ), ); - } else if (!purpleAiQueryLabel.label) { + } else if (!oobeeAiQueryLabel.label) { document.getElementById(accordionDiv).innerHTML = `Processing AI suggestions, please check back later.` } else { - await getPurpleAiAnswer(ruleId, accordionDiv, purpleAiQueryLabel.label, buttonsDiv, aiErrorDiv); + await getPurpleAiAnswer(ruleId, accordionDiv, oobeeAiQueryLabel.label, buttonsDiv, aiErrorDiv); } } diff --git a/src/static/ejs/partials/summaryHeader.ejs b/src/static/ejs/partials/summaryHeader.ejs index 73ab433a..f1e9b80b 100644 --- a/src/static/ejs/partials/summaryHeader.ejs +++ b/src/static/ejs/partials/summaryHeader.ejs @@ -46,7 +46,7 @@ /> - Purple A11y Scan Summary + Oobee Scan Summary <%# diff --git a/src/static/ejs/partials/summaryMain.ejs b/src/static/ejs/partials/summaryMain.ejs index f2f99c23..c8620ac8 100644 --- a/src/static/ejs/partials/summaryMain.ejs +++ b/src/static/ejs/partials/summaryMain.ejs @@ -63,7 +63,7 @@ (Conformance Level A & AA) Success Criteria can be automatically checked so manual testing diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index 6169f39c..c41a5039 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -251,7 +251,7 @@ itemsElement.innerHTML = itemsContent; var phAppVersionElement = document.getElementById('phAppVersion'); - var versionContent = 'Oobee Desktop Version ' + scanData.phAppVersion; + var versionContent = 'Oobee Version ' + scanData.phAppVersion; phAppVersionElement.innerHTML = versionContent; var isCustomFlow = scanData.isCustomFlow; diff --git a/src/static/ejs/summary.ejs b/src/static/ejs/summary.ejs index 6757a79b..472dc8ab 100644 --- a/src/static/ejs/summary.ejs +++ b/src/static/ejs/summary.ejs @@ -3,7 +3,7 @@ - Purple A11y Scan Summary + Oobee Scan Summary - + IMPACT @@ -1594,7 +1594,7 @@
purpleA11y-pl async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -520,12 +522,12 @@ On your project's root folder, create a Playwright test file purpleA11y-pl // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); -Run your test with node purpleA11y-playwright-demo.js . +Run your test with node oobeeA11y-playwright-demo.js . -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -535,9 +537,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats typescript --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee typescript --save-dev and npx playwright install Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -552,17 +555,17 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -Create a sub-folder and Playwright test file src/purpleA11y-playwright-demo.ts with the following contents: +Create a sub-folder and Playwright test file src/oobeeA11y-playwright-demo.ts with the following contents: import { Browser, BrowserContext, Page, chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; declare const runA11yScan: (elementsToScan?: string[]) => Promise; @@ -587,7 +590,7 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -610,12 +613,12 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -777,6 +780,6 @@ You will see Purple A11y results generated in results folder. }); }; - runScript(); + runScript(); diff --git a/README.md b/README.md index 4bcc2aef..57625f0b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# Purple A11y +# Oobee -[Purple A11y](https://go.gov.sg/purple-a11y-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). - -This is the engine and command-line interface (CLI) for Purple A11y. For a desktop graphical user interface (GUI), check out [Purple A11y Desktop](https://go.gov.sg/purple-a11y). The official application can only be downloaded at [https://go.gov.sg/purple-a11y-cicd](https://go.gov.sg/purple-a11y-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. +[Oobee](https://go.gov.sg/oobee-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). +This is the engine and command-line interface (CLI) for Oobee. For a desktop graphical user interface (GUI), check out [Oobee Desktop](https://go.gov.sg/oobee). The official application can only be downloaded at [https://go.gov.sg/oobee-cicd](https://go.gov.sg/oobee-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. ## Technology Stack @@ -15,27 +14,31 @@ This is the engine and command-line interface (CLI) for Purple A11y. For a desk 6. [Corretto](https://aws.amazon.com/corretto) 7. [VeraPDF](https://github.com/veraPDF/veraPDF-apps) -## Using Purple A11y as a NodeJS module +## Using Oobee as a NodeJS module -If you wish to use Purple A11y as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. +If you wish to use Oobee as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. ## Prerequisites and Installations -### Portable Purple A11y +### Portable Oobee -Portable Purple A11y is the recommended way to run Purple A11y as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Purple A11y. +Portable Oobee is the recommended way to run Oobee as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Oobee. ### Manual Installation Please ensure the following requirements are met: #### Node.js + - A Node distribution of 20 (LTS) or above. - To check your version of Node, go into terminal and paste the command bellow + ```shell node -v ``` -- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + +- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + ```shell # Install NodeJS version with NVM nvm install --lts @@ -43,20 +46,26 @@ nvm install --lts # For subsequent use, you will need to run the command below each time you open a new terminal nvm use --lts ``` + - Install the required NPM packages with `npm install`. - Build the project with `npm run build` before you try to run it with `npm start`. #### Java JRE/JDK + - A JRE/JDK distribution of version 11 or above. - To check your version of Java, go into terminal and paste the command bellow + ```shell java --version ``` + - If you do not have java, you can consider installing [Corretto](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html) distribution of OpenJDK. #### VeraPDF -- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. + +- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. - Ensure you have VeraPDF set in PATH then verify verapdf is installed correctly: + ```shell # Invoke the VeraPDF installer # Windows users should use vera-install.bat instead of vera-install @@ -77,22 +86,22 @@ Please refer to [Troubleshooting section](#troubleshooting) for more information ## Features -Purple A11y can perform the following to scan the target URL. +Oobee can perform the following to scan the target URL. -- To **run** Purple A11y in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. +- To **run** Oobee in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. - Results will be compiled in JSON format, followed by generating a HTML report. > NOTE: For your initial scan, there may be some loading time required before use. Purple-A11y will also ask for your name and email address and collect your app usage data to personalise your experience. Your information fully complies with [GovTech’s Privacy Policy](https://www.tech.gov.sg/privacy/). #### Delete/Edit Details + > You may delete and edit your cached name and e-mail address by running the following command to delete `userData.txt`: -> - Windows (PowerShell): `rm "$env:APPDATA\Purple A11y\userData.txt"` -> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Purple A11y/userData.txt"` +> - Windows (PowerShell): `rm "$env:APPDATA\Oobee\userData.txt"` +> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Oobee/userData.txt"` If `userData.txt` does not exists just run `npm start`. - ### Scan Selection You can interact via your arrow keys. @@ -100,7 +109,7 @@ You can interact via your arrow keys. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience.│ │ │ │ Welcome back User! │ @@ -119,14 +128,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? (Y/n) No +? Do you want oobee to run in the background? (Y/n) No ``` ### Sitemap Scan @@ -134,14 +143,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL or file path to sitemap, or drag and drop a sitemap file here: https://www.sitemaps.org/sitemap.xml @@ -154,7 +163,7 @@ Headless mode would allow you to run the scan in the background. If you would li Scanning website... -#purple-a11y will then start scraping from the file link provided above. +#oobee will then start scraping from the file link provided above. #Console results ``` @@ -170,14 +179,14 @@ If the sitemap URL provided is invalid, an error message will be prompted for yo ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? Yes +? Do you want oobee to run in the background? Yes ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL of website: https://www.domain.org @@ -191,19 +200,19 @@ If the website URL provided is invalid, an error message will be prompted for yo ### Customised Mobile Device Scan -``` shell +```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) (Use arrow keys) -❯ Desktop +❯ Desktop Mobile Custom ``` @@ -212,14 +221,14 @@ Choose `Mobile` for a default mobile screen size scan and `Custom` to choose a d ### Custom flow -Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. +Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. 1. Start by choosing the `Custom flow` in the menu selection. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ @@ -229,10 +238,10 @@ Custom flow allows you to specify a user journey by enabling you to click the sc Sitemap Website ❯ Custom - ``` +``` 1. Specify the URL of the starting page you wish to scan -2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. +2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. 3. You may drag the top black bar to the bottom of the page in the event it prevents you from viewing / blocking certain page elements. 4. Close the Chrome window to end the scan. @@ -240,11 +249,10 @@ Other options: - You can specify sites to exclude from accessibility scan (e.g. login page) by adding a pattern of the domain to `exclusions.txt`. An example of `exclusions.txt`: -``` txt +```txt \.*login.singpass.gov.sg\.* ``` - #### Known Issues If the custom flow fails to start, you might be running multiple versions of Playwright. Re-install Playwright: @@ -259,9 +267,8 @@ npx playwright@1.27.1 install ### CLI Mode -CLI mode is designed to be run in continuous integration (CI) environment. - Run `npm run cli` for a set of command-line parameters available. - +CLI mode is designed to be run in continuous integration (CI) environment. +Run `npm run cli` for a set of command-line parameters available. ```shell Usage: npm run cli -- -c -d -w -If the device name contains ```(``` and ```)```, wrap the device name in single quotes when entered into the CLI. -Please note that ```-d``` and ```-w``` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. +If the device name contains `(` and `)`, wrap the device name in single quotes when entered into the CLI. +Please note that `-d` and `-w` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' +npm run cli -- -c 2 -o oobee-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' ``` If the site you want to scan has a query string wrap the link in single quotes when entered into the CLI. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with a custom screen width '360', run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with a custom screen width '360', run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u "http://localhost:8000" -w 360 +npm run cli -- -c 2 -o oobee-scan-results.zip -u "http://localhost:8000" -w 360 ``` ## Report -Once a scan of the site is completed. + +Once a scan of the site is completed. A report will be downloaded into the current working directory. ## Accessibility Scan Results -Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). +Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). -For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). +For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). ## Troubleshooting @@ -503,12 +511,12 @@ Please refer to the information below to assist in debugging. Most errors below **Issue**: When your Node.js version is incompatible, you may face the following syntax error. - ```shell const URL_NO_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line ^ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@:%\._\+~#=]{0,254}[\p{L}0-9]\.[a-z]{2,63}(:\d{1,5})?(/[-\p{L}0-9@:%_\+.~#?&//=\(\)]*)?/: Invalid escape ``` + **Solution**: Install Node.js versions >= 20, i.e. Node.js v20 and above. ### Compiled against a different Node.js version @@ -516,7 +524,7 @@ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@ **Issue**: When you switch between different versions of Node.js in your environment, you may face the following error. ```shell -/purple-a11y/node_modules/bindings/bindings.js:91 +/oobee/node_modules/bindings/bindings.js:91 throw e ^ @@ -531,15 +539,15 @@ the module (for instance, using `npm rebuild` or `npm install`). ### dyld Error -**Issue**: Not able to run Purple A11y due to the following error shown below +**Issue**: Not able to run Oobee due to the following error shown below ```shell dyld: lazy symbol binding failed: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace dyld: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /PURPLE_A11y/purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /PURPLE_A11y/oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace zsh: abort node index.js @@ -554,7 +562,7 @@ zsh: abort node index.js **Limitation**: Due to animations causing elements to shift out of the viewport after an Axe scan, there's a risk of element screenshots timing out within 5 seconds if the element is not found. This known issue is particularly prevalent in scenarios like carousels with interval-based transitions. -## FAQ +## FAQ ### How do I limit number of pages scanned? @@ -566,9 +574,8 @@ To do this, run CLI mode `npm run cli --` with the needed settings and specify ` We recommend looking at our **Technology Stack** to understand the usage of each component. Take your time to understand. - ## Additional Information on Data -Purple A11y uses third-party open-source tools that may be downloaded over the Internet during the installation process of Purple A11y. Users should be aware of the libraries used by examining `package.json`. +Oobee uses third-party open-source tools that may be downloaded over the Internet during the installation process of Oobee. Users should be aware of the libraries used by examining `package.json`. -Purple A11y may send information to the website, URL and HTML code snippets where the user chooses to initiate a Purple A11y scan for telemetry purposes. +Oobee may send information to the website, URL and HTML code snippets where the user chooses to initiate a Oobee scan for telemetry purposes. diff --git a/__mocks__/mock-report.html b/__mocks__/mock-report.html index b08801be..8ca6ee93 100644 --- a/__mocks__/mock-report.html +++ b/__mocks__/mock-report.html @@ -523,11 +523,11 @@ body.dark .footer { background-color: #272727; } - #a11y-table { + #oobee-table { background-color: #fff; width: 100%; } - body.dark #a11y-table { + body.dark #oobee-table { background-color: #272727; } table.dataTable { @@ -1117,7 +1117,7 @@ Accessibility Report - + IMPACT @@ -1151,7 +1151,7 @@ Accessibility Report @@ -1204,7 +1204,7 @@ Accessibility Report @@ -1257,7 +1257,7 @@ Accessibility Report @@ -1310,7 +1310,7 @@ Accessibility Report @@ -1374,7 +1374,7 @@ Accessibility Report diff --git a/src/static/ejs/partials/scripts/categorySummary.ejs b/src/static/ejs/partials/scripts/categorySummary.ejs index 6545b94a..9a2ff175 100644 --- a/src/static/ejs/partials/scripts/categorySummary.ejs +++ b/src/static/ejs/partials/scripts/categorySummary.ejs @@ -51,8 +51,8 @@ filteredItems[category].rules.forEach((rule, index) => { const buttonAriaLabel = `${rule.description}, ${rule.totalItems} occurrences`; - const purpleAiSvgId = `${category}-${rule.rule}-${index}`; - const isPurpleAiRule = purpleAiRules.includes(rule.rule); + const oobeeAiSvgId = `${category}-${rule.rule}-${index}`; + const isPurpleAiRule = oobeeAiRules.includes(rule.rule); // START new createElementFromString const ruleItem = createElementFromString(` @@ -67,8 +67,8 @@ ${ isPurpleAiRule ? `aria-describedby="containsAISuggestions" - onfocus="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" - onblur="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" + onfocus="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" + onblur="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" onmousedown="event.preventDefault()"` : `` } @@ -83,7 +83,7 @@ ${htmlEscapeString(rule.description)} ${ isPurpleAiRule - ? ` diff --git a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs index 38420722..ef8da4bc 100644 --- a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +++ b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs @@ -97,7 +97,7 @@ category summary is clicked %> `), ); - if (purpleAiRules.includes(selectedRule.rule)) { + if (oobeeAiRules.includes(selectedRule.rule)) { document.querySelector('#expandedRuleAiFeedback').style.display = 'block'; } else { document.querySelector('#expandedRuleAiFeedback').style.display = 'none'; @@ -535,10 +535,10 @@ category summary is clicked %> const buttonDivForAiFeedback = `${buttonAIId}-${index}`; const aiErrorDiv = `${errorAIId}-${index}`; let itemCard; - const isPurpleAiRule = purpleAiRules.includes(ruleInCategory.rule); - let purpleAiQueryLabel; + const isPurpleAiRule = oobeeAiRules.includes(ruleInCategory.rule); + let oobeeAiQueryLabel; if (isPurpleAiRule) { - purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); + oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); } itemCard = createElementFromString(` @@ -621,7 +621,7 @@ category summary is clicked %> AI suggestion - ${purpleAiQueryLabel.hasNetworkError ? + ${oobeeAiQueryLabel.hasNetworkError ? ` Generate response ` : - (purpleAiQueryLabel.label ? + (oobeeAiQueryLabel.label ? ` diff --git a/src/static/ejs/partials/scripts/utils.ejs b/src/static/ejs/partials/scripts/utils.ejs index 9c4b18f7..3b573640 100644 --- a/src/static/ejs/partials/scripts/utils.ejs +++ b/src/static/ejs/partials/scripts/utils.ejs @@ -6,8 +6,8 @@ return tempContainer.firstChild; } - const purpleAiHtmlETL = <%- purpleAi.htmlETL %>; - const purpleAiRules = <%- JSON.stringify(purpleAi.rules) %>; + const oobeeAiHtmlETL = <%- oobeeAi.htmlETL %>; + const oobeeAiRules = <%- JSON.stringify(oobeeAi.rules) %>; // extract tagname and attribute name from html tag // e.g. ["input", "type", "value", "role"] from @@ -217,14 +217,14 @@ const api = memoizeApiCall(); const apiUrls = { - catalog: 'https://govtechsg.github.io/purple-ai/catalog.json', - getRuleIdData: (ruleId) => `https://govtechsg.github.io/purple-ai/results/${ruleId}.json` + catalog: 'https://govtechsg.github.io/oobee-ai/catalog.json', + getRuleIdData: (ruleId) => `https://govtechsg.github.io/oobee-ai/results/${ruleId}.json` } const isOffline = () => !window.navigator.onLine; const checkPurpleAiQueryLabel = async (ruleId, ruleHtml) => { - const purpleAiQueryLabel = { + const oobeeAiQueryLabel = { label: null, hasNetworkError: false, hasGenericError: false @@ -233,7 +233,7 @@ return api(apiUrls.catalog).then(catalogData => { // no information for current rule if (!catalogData[ruleId] || catalogData[ruleId].length === 0) { - return purpleAiQueryLabel; + return oobeeAiQueryLabel; } if (rulesUsingRoles.includes(ruleId)) { @@ -244,18 +244,18 @@ if (roleForHtml) { const currentLabel = `${htmlElement}_${roleForHtml}`.trim(); const foundLabel = catalogData[ruleId].find(label => label === currentLabel); - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; + return oobeeAiQueryLabel; } } // e.g. li_aria-controls_aria-selected_role - const currentLabelList = getHtmlTagAndAttributes(purpleAiHtmlETL(ruleHtml)); + const currentLabelList = getHtmlTagAndAttributes(oobeeAiHtmlETL(ruleHtml)); const currentLabel = currentLabelList.join('_'); if (catalogData[ruleId].includes(currentLabel)) { - purpleAiQueryLabel.label = escapeHtmlForAI(currentLabel); - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = escapeHtmlForAI(currentLabel); + return oobeeAiQueryLabel; } // count the number of elements in keyArr that @@ -269,8 +269,8 @@ return attrMatch.length >= 3; }) - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; + return oobeeAiQueryLabel; }) .catch(err => { console.error(`An error has occurred while checking if ${ruleId} needs AI query`); @@ -291,8 +291,8 @@ } const handleOfflinePurpleAi = async (ruleId, accordionDiv, html, buttonsDiv, aiErrorDiv) => { - let purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); - if (purpleAiQueryLabel.hasNetworkError) { + let oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); + if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -300,7 +300,7 @@ `This feature requires internet connection. Please try again`, ), ); - } else if (purpleAiQueryLabel.hasNetworkError) { + } else if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -308,10 +308,10 @@ `Something went wrong. Please try again`, ), ); - } else if (!purpleAiQueryLabel.label) { + } else if (!oobeeAiQueryLabel.label) { document.getElementById(accordionDiv).innerHTML = `Processing AI suggestions, please check back later.` } else { - await getPurpleAiAnswer(ruleId, accordionDiv, purpleAiQueryLabel.label, buttonsDiv, aiErrorDiv); + await getPurpleAiAnswer(ruleId, accordionDiv, oobeeAiQueryLabel.label, buttonsDiv, aiErrorDiv); } } diff --git a/src/static/ejs/partials/summaryHeader.ejs b/src/static/ejs/partials/summaryHeader.ejs index 73ab433a..f1e9b80b 100644 --- a/src/static/ejs/partials/summaryHeader.ejs +++ b/src/static/ejs/partials/summaryHeader.ejs @@ -46,7 +46,7 @@ /> - Purple A11y Scan Summary + Oobee Scan Summary <%# diff --git a/src/static/ejs/partials/summaryMain.ejs b/src/static/ejs/partials/summaryMain.ejs index f2f99c23..c8620ac8 100644 --- a/src/static/ejs/partials/summaryMain.ejs +++ b/src/static/ejs/partials/summaryMain.ejs @@ -63,7 +63,7 @@ (Conformance Level A & AA) Success Criteria can be automatically checked so manual testing diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index 6169f39c..c41a5039 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -251,7 +251,7 @@ itemsElement.innerHTML = itemsContent; var phAppVersionElement = document.getElementById('phAppVersion'); - var versionContent = 'Oobee Desktop Version ' + scanData.phAppVersion; + var versionContent = 'Oobee Version ' + scanData.phAppVersion; phAppVersionElement.innerHTML = versionContent; var isCustomFlow = scanData.isCustomFlow; diff --git a/src/static/ejs/summary.ejs b/src/static/ejs/summary.ejs index 6757a79b..472dc8ab 100644 --- a/src/static/ejs/summary.ejs +++ b/src/static/ejs/summary.ejs @@ -3,7 +3,7 @@ - Purple A11y Scan Summary + Oobee Scan Summary - + IMPACT @@ -1594,7 +1594,7 @@
purpleA11y-pl // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); -Run your test with node purpleA11y-playwright-demo.js . +Run your test with node oobeeA11y-playwright-demo.js . -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -535,9 +537,10 @@ Create a package.json by running npm init . Accept the Change the type of npm package to module by running npm pkg set type="module" -Install the following node dependencies by running npm install playwright @govtechsg/purple-hats typescript --save-dev and npx playwright install +Install the following node dependencies by running npm install playwright @govtechsg/oobee typescript --save-dev and npx playwright install Create a tsconfig.json in the root directory and add the following: + ``` { "compilerOptions": { @@ -552,17 +555,17 @@ Create a tsconfig.json in the root directory and add the following: } ``` -Navigate to node_modules/@govtechsg/purple-hats and run npm install and npm run build within the folder to install remaining Purple A11y dependencies: +Navigate to node_modules/@govtechsg/oobee and run npm install and npm run build within the folder to install remaining Oobee dependencies: - cd node_modules/@govtechsg/purple-hats + cd node_modules/@govtechsg/oobee npm install npm run build cd ../../.. -Create a sub-folder and Playwright test file src/purpleA11y-playwright-demo.ts with the following contents: +Create a sub-folder and Playwright test file src/oobeeA11y-playwright-demo.ts with the following contents: import { Browser, BrowserContext, Page, chromium } from "playwright"; - import purpleA11yInit from "@govtechsg/purple-hats"; + import oobeeA11yInit from "@govtechsg/oobee"; declare const runA11yScan: (elementsToScan?: string[]) => Promise; @@ -587,7 +590,7 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -610,12 +613,12 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder. @@ -777,6 +780,6 @@ You will see Purple A11y results generated in results folder. }); }; - runScript(); + runScript(); diff --git a/README.md b/README.md index 4bcc2aef..57625f0b 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,8 @@ -# Purple A11y +# Oobee -[Purple A11y](https://go.gov.sg/purple-a11y-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). - -This is the engine and command-line interface (CLI) for Purple A11y. For a desktop graphical user interface (GUI), check out [Purple A11y Desktop](https://go.gov.sg/purple-a11y). The official application can only be downloaded at [https://go.gov.sg/purple-a11y-cicd](https://go.gov.sg/purple-a11y-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. +[Oobee](https://go.gov.sg/oobee-cli) is a customisable, automated accessibility testing tool that allows software development teams to assess whether their products are user-friendly to persons with disabilities (PWDs). +This is the engine and command-line interface (CLI) for Oobee. For a desktop graphical user interface (GUI), check out [Oobee Desktop](https://go.gov.sg/oobee). The official application can only be downloaded at [https://go.gov.sg/oobee-cicd](https://go.gov.sg/oobee-cicd). We recommend that you download the software only from the official link, as other sources and/or third party links may pose risks and/or compromise your system. ## Technology Stack @@ -15,27 +14,31 @@ This is the engine and command-line interface (CLI) for Purple A11y. For a desk 6. [Corretto](https://aws.amazon.com/corretto) 7. [VeraPDF](https://github.com/veraPDF/veraPDF-apps) -## Using Purple A11y as a NodeJS module +## Using Oobee as a NodeJS module -If you wish to use Purple A11y as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. +If you wish to use Oobee as a NodeJS module that can be integrated with end-to-end testing frameworks, refer to the [integration guide](./INTEGRATION.md) on how you can do so. ## Prerequisites and Installations -### Portable Purple A11y +### Portable Oobee -Portable Purple A11y is the recommended way to run Purple A11y as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Purple A11y. +Portable Oobee is the recommended way to run Oobee as it reduces the difficulty for installation. Refer to [Installation Guide](./INSTALLATION.md) for step-by-step instructions for portable Oobee. ### Manual Installation Please ensure the following requirements are met: #### Node.js + - A Node distribution of 20 (LTS) or above. - To check your version of Node, go into terminal and paste the command bellow + ```shell node -v ``` -- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + +- If you do not have node, or if there is a need to manage your node versions, you can consider using [Node Version Manager (NVM)](https://github.com/nvm-sh/nvm). After NVM is installed, you can then install an LTS version of Node: + ```shell # Install NodeJS version with NVM nvm install --lts @@ -43,20 +46,26 @@ nvm install --lts # For subsequent use, you will need to run the command below each time you open a new terminal nvm use --lts ``` + - Install the required NPM packages with `npm install`. - Build the project with `npm run build` before you try to run it with `npm start`. #### Java JRE/JDK + - A JRE/JDK distribution of version 11 or above. - To check your version of Java, go into terminal and paste the command bellow + ```shell java --version ``` + - If you do not have java, you can consider installing [Corretto](https://docs.aws.amazon.com/corretto/latest/corretto-11-ug/what-is-corretto-11.html) distribution of OpenJDK. #### VeraPDF -- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. + +- VeraPDF is used for scanning PDF files. Install VeraPDF by following the [install guide](https://docs.verapdf.org/install/). You may wish to use the Automated installation script provided on that page, and changing the XML installation script section `/tmp/verapdf-test` to a location of your choice. - Ensure you have VeraPDF set in PATH then verify verapdf is installed correctly: + ```shell # Invoke the VeraPDF installer # Windows users should use vera-install.bat instead of vera-install @@ -77,22 +86,22 @@ Please refer to [Troubleshooting section](#troubleshooting) for more information ## Features -Purple A11y can perform the following to scan the target URL. +Oobee can perform the following to scan the target URL. -- To **run** Purple A11y in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. +- To **run** Oobee in **terminal**, run `npm start`. Questions will be prompted to assist you in providing the right inputs. - Results will be compiled in JSON format, followed by generating a HTML report. > NOTE: For your initial scan, there may be some loading time required before use. Purple-A11y will also ask for your name and email address and collect your app usage data to personalise your experience. Your information fully complies with [GovTech’s Privacy Policy](https://www.tech.gov.sg/privacy/). #### Delete/Edit Details + > You may delete and edit your cached name and e-mail address by running the following command to delete `userData.txt`: -> - Windows (PowerShell): `rm "$env:APPDATA\Purple A11y\userData.txt"` -> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Purple A11y/userData.txt"` +> - Windows (PowerShell): `rm "$env:APPDATA\Oobee\userData.txt"` +> - MacOS (Terminal): `rm "$HOME/Library/Application Support/Oobee/userData.txt"` If `userData.txt` does not exists just run `npm start`. - ### Scan Selection You can interact via your arrow keys. @@ -100,7 +109,7 @@ You can interact via your arrow keys. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience.│ │ │ │ Welcome back User! │ @@ -119,14 +128,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? (Y/n) No +? Do you want oobee to run in the background? (Y/n) No ``` ### Sitemap Scan @@ -134,14 +143,14 @@ Headless mode would allow you to run the scan in the background. If you would li ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Sitemap -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL or file path to sitemap, or drag and drop a sitemap file here: https://www.sitemaps.org/sitemap.xml @@ -154,7 +163,7 @@ Headless mode would allow you to run the scan in the background. If you would li Scanning website... -#purple-a11y will then start scraping from the file link provided above. +#oobee will then start scraping from the file link provided above. #Console results ``` @@ -170,14 +179,14 @@ If the sitemap URL provided is invalid, an error message will be prompted for yo ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? Yes +? Do you want oobee to run in the background? Yes ? Which screen size would you like to scan? (Use arrow keys) Desktop ? Please enter URL of website: https://www.domain.org @@ -191,19 +200,19 @@ If the website URL provided is invalid, an error message will be prompted for yo ### Customised Mobile Device Scan -``` shell +```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ │ (Refer to readme.txt on how to change your profile) │ └────────────────────────────────────────────────────────────┘ ? What would you like to scan? Website -? Do you want purple-a11y to run in the background? No +? Do you want oobee to run in the background? No ? Which screen size would you like to scan? (Use arrow keys) (Use arrow keys) -❯ Desktop +❯ Desktop Mobile Custom ``` @@ -212,14 +221,14 @@ Choose `Mobile` for a default mobile screen size scan and `Custom` to choose a d ### Custom flow -Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. +Custom flow allows you to specify a user journey by enabling you to click the scan button on each desired webpage on a browser to initiate scan. This is useful to scan websites that require user and form input. 1. Start by choosing the `Custom flow` in the menu selection. ```shell % npm start ┌────────────────────────────────────────────────────────────┐ -│ Purple A11y (ver ) │ +│ Oobee (ver ) │ │ We recommend using Chrome browser for the best experience. │ │ │ │ Welcome back User! │ @@ -229,10 +238,10 @@ Custom flow allows you to specify a user journey by enabling you to click the sc Sitemap Website ❯ Custom - ``` +``` 1. Specify the URL of the starting page you wish to scan -2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. +2. A Chrome window will appear. Navigate through the pages and click on the **Scan this page** button at the top right of the broswer's page to conduct an accessibility scan on the current page. 3. You may drag the top black bar to the bottom of the page in the event it prevents you from viewing / blocking certain page elements. 4. Close the Chrome window to end the scan. @@ -240,11 +249,10 @@ Other options: - You can specify sites to exclude from accessibility scan (e.g. login page) by adding a pattern of the domain to `exclusions.txt`. An example of `exclusions.txt`: -``` txt +```txt \.*login.singpass.gov.sg\.* ``` - #### Known Issues If the custom flow fails to start, you might be running multiple versions of Playwright. Re-install Playwright: @@ -259,9 +267,8 @@ npx playwright@1.27.1 install ### CLI Mode -CLI mode is designed to be run in continuous integration (CI) environment. - Run `npm run cli` for a set of command-line parameters available. - +CLI mode is designed to be run in continuous integration (CI) environment. +Run `npm run cli` for a set of command-line parameters available. ```shell Usage: npm run cli -- -c -d -w -If the device name contains ```(``` and ```)```, wrap the device name in single quotes when entered into the CLI. -Please note that ```-d``` and ```-w``` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. +If the device name contains `(` and `)`, wrap the device name in single quotes when entered into the CLI. +Please note that `-d` and `-w` are mutually exclusive. If none are specified, the default device used for the CLI scan is Desktop. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with an 'iPad (gen 7) landscape' screen, run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' +npm run cli -- -c 2 -o oobee-scan-results.zip -u http://localhost:8000 -d 'iPad (gen 7) landscape' ``` If the site you want to scan has a query string wrap the link in single quotes when entered into the CLI. -For example, to conduct a website scan to the URL "http://localhost:8000" and write to "a11y-scan-results.zip" with a custom screen width '360', run +For example, to conduct a website scan to the URL "http://localhost:8000" and write to "oobee-scan-results.zip" with a custom screen width '360', run ```shell -npm run cli -- -c 2 -o a11y-scan-results.zip -u "http://localhost:8000" -w 360 +npm run cli -- -c 2 -o oobee-scan-results.zip -u "http://localhost:8000" -w 360 ``` ## Report -Once a scan of the site is completed. + +Once a scan of the site is completed. A report will be downloaded into the current working directory. ## Accessibility Scan Results -Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). +Each Issue has its own severity "Must Fix" / "Good to Fix" based on the [WCAG 2.2 Conformance](https://www.w3.org/TR/WCAG22/). -For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). +For details on which accessibility scan results triggers a "Must Fix" / "Good to Fix" findings, you may refer to [Scan Issue Details](./DETAILS.md). ## Troubleshooting @@ -503,12 +511,12 @@ Please refer to the information below to assist in debugging. Most errors below **Issue**: When your Node.js version is incompatible, you may face the following syntax error. - ```shell const URL_NO_COMMAS_REGEX = RegExp('https?://(www\\.)?[\\p{L}0-9][-\\p{L}0-9@:%._\\+~#=]{0,254}[\\p{L}0-9]\\.[a-z]{2,63}(:\\d{1,5})?(/[-\\p{L}0-9@:%_\\+.~#?&//=\\(\\)]*)?', 'giu'); // eslint-disable-line ^ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@:%\._\+~#=]{0,254}[\p{L}0-9]\.[a-z]{2,63}(:\d{1,5})?(/[-\p{L}0-9@:%_\+.~#?&//=\(\)]*)?/: Invalid escape ``` + **Solution**: Install Node.js versions >= 20, i.e. Node.js v20 and above. ### Compiled against a different Node.js version @@ -516,7 +524,7 @@ SyntaxError: Invalid regular expression: /https?://(www\.)?[\p{L}0-9][-\p{L}0-9@ **Issue**: When you switch between different versions of Node.js in your environment, you may face the following error. ```shell -/purple-a11y/node_modules/bindings/bindings.js:91 +/oobee/node_modules/bindings/bindings.js:91 throw e ^ @@ -531,15 +539,15 @@ the module (for instance, using `npm rebuild` or `npm install`). ### dyld Error -**Issue**: Not able to run Purple A11y due to the following error shown below +**Issue**: Not able to run Oobee due to the following error shown below ```shell dyld: lazy symbol binding failed: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace dyld: Symbol not found: __ZN2v87Isolate37AdjustAmountOfExternalAllocatedMemoryEx - Referenced from: /PURPLE_A11y/purple-a11y/node_modules/libxmljs/build/Release/xmljs.node + Referenced from: /PURPLE_A11y/oobee/node_modules/libxmljs/build/Release/xmljs.node Expected in: flat namespace zsh: abort node index.js @@ -554,7 +562,7 @@ zsh: abort node index.js **Limitation**: Due to animations causing elements to shift out of the viewport after an Axe scan, there's a risk of element screenshots timing out within 5 seconds if the element is not found. This known issue is particularly prevalent in scenarios like carousels with interval-based transitions. -## FAQ +## FAQ ### How do I limit number of pages scanned? @@ -566,9 +574,8 @@ To do this, run CLI mode `npm run cli --` with the needed settings and specify ` We recommend looking at our **Technology Stack** to understand the usage of each component. Take your time to understand. - ## Additional Information on Data -Purple A11y uses third-party open-source tools that may be downloaded over the Internet during the installation process of Purple A11y. Users should be aware of the libraries used by examining `package.json`. +Oobee uses third-party open-source tools that may be downloaded over the Internet during the installation process of Oobee. Users should be aware of the libraries used by examining `package.json`. -Purple A11y may send information to the website, URL and HTML code snippets where the user chooses to initiate a Purple A11y scan for telemetry purposes. +Oobee may send information to the website, URL and HTML code snippets where the user chooses to initiate a Oobee scan for telemetry purposes. diff --git a/__mocks__/mock-report.html b/__mocks__/mock-report.html index b08801be..8ca6ee93 100644 --- a/__mocks__/mock-report.html +++ b/__mocks__/mock-report.html @@ -523,11 +523,11 @@ body.dark .footer { background-color: #272727; } - #a11y-table { + #oobee-table { background-color: #fff; width: 100%; } - body.dark #a11y-table { + body.dark #oobee-table { background-color: #272727; } table.dataTable { @@ -1117,7 +1117,7 @@ Accessibility Report - + IMPACT @@ -1151,7 +1151,7 @@ Accessibility Report @@ -1204,7 +1204,7 @@ Accessibility Report @@ -1257,7 +1257,7 @@ Accessibility Report @@ -1310,7 +1310,7 @@ Accessibility Report @@ -1374,7 +1374,7 @@ Accessibility Report diff --git a/src/static/ejs/partials/scripts/categorySummary.ejs b/src/static/ejs/partials/scripts/categorySummary.ejs index 6545b94a..9a2ff175 100644 --- a/src/static/ejs/partials/scripts/categorySummary.ejs +++ b/src/static/ejs/partials/scripts/categorySummary.ejs @@ -51,8 +51,8 @@ filteredItems[category].rules.forEach((rule, index) => { const buttonAriaLabel = `${rule.description}, ${rule.totalItems} occurrences`; - const purpleAiSvgId = `${category}-${rule.rule}-${index}`; - const isPurpleAiRule = purpleAiRules.includes(rule.rule); + const oobeeAiSvgId = `${category}-${rule.rule}-${index}`; + const isPurpleAiRule = oobeeAiRules.includes(rule.rule); // START new createElementFromString const ruleItem = createElementFromString(` @@ -67,8 +67,8 @@ ${ isPurpleAiRule ? `aria-describedby="containsAISuggestions" - onfocus="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" - onblur="document.getElementById('${purpleAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" + onfocus="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseover'))" + onblur="document.getElementById('${oobeeAiSvgId}').dispatchEvent(new MouseEvent('mouseout'))" onmousedown="event.preventDefault()"` : `` } @@ -83,7 +83,7 @@ ${htmlEscapeString(rule.description)} ${ isPurpleAiRule - ? ` diff --git a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs index 38420722..ef8da4bc 100644 --- a/src/static/ejs/partials/scripts/ruleOffcanvas.ejs +++ b/src/static/ejs/partials/scripts/ruleOffcanvas.ejs @@ -97,7 +97,7 @@ category summary is clicked %> `), ); - if (purpleAiRules.includes(selectedRule.rule)) { + if (oobeeAiRules.includes(selectedRule.rule)) { document.querySelector('#expandedRuleAiFeedback').style.display = 'block'; } else { document.querySelector('#expandedRuleAiFeedback').style.display = 'none'; @@ -535,10 +535,10 @@ category summary is clicked %> const buttonDivForAiFeedback = `${buttonAIId}-${index}`; const aiErrorDiv = `${errorAIId}-${index}`; let itemCard; - const isPurpleAiRule = purpleAiRules.includes(ruleInCategory.rule); - let purpleAiQueryLabel; + const isPurpleAiRule = oobeeAiRules.includes(ruleInCategory.rule); + let oobeeAiQueryLabel; if (isPurpleAiRule) { - purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); + oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleInCategory.rule, item.html); } itemCard = createElementFromString(` @@ -621,7 +621,7 @@ category summary is clicked %> AI suggestion - ${purpleAiQueryLabel.hasNetworkError ? + ${oobeeAiQueryLabel.hasNetworkError ? ` Generate response ` : - (purpleAiQueryLabel.label ? + (oobeeAiQueryLabel.label ? ` diff --git a/src/static/ejs/partials/scripts/utils.ejs b/src/static/ejs/partials/scripts/utils.ejs index 9c4b18f7..3b573640 100644 --- a/src/static/ejs/partials/scripts/utils.ejs +++ b/src/static/ejs/partials/scripts/utils.ejs @@ -6,8 +6,8 @@ return tempContainer.firstChild; } - const purpleAiHtmlETL = <%- purpleAi.htmlETL %>; - const purpleAiRules = <%- JSON.stringify(purpleAi.rules) %>; + const oobeeAiHtmlETL = <%- oobeeAi.htmlETL %>; + const oobeeAiRules = <%- JSON.stringify(oobeeAi.rules) %>; // extract tagname and attribute name from html tag // e.g. ["input", "type", "value", "role"] from @@ -217,14 +217,14 @@ const api = memoizeApiCall(); const apiUrls = { - catalog: 'https://govtechsg.github.io/purple-ai/catalog.json', - getRuleIdData: (ruleId) => `https://govtechsg.github.io/purple-ai/results/${ruleId}.json` + catalog: 'https://govtechsg.github.io/oobee-ai/catalog.json', + getRuleIdData: (ruleId) => `https://govtechsg.github.io/oobee-ai/results/${ruleId}.json` } const isOffline = () => !window.navigator.onLine; const checkPurpleAiQueryLabel = async (ruleId, ruleHtml) => { - const purpleAiQueryLabel = { + const oobeeAiQueryLabel = { label: null, hasNetworkError: false, hasGenericError: false @@ -233,7 +233,7 @@ return api(apiUrls.catalog).then(catalogData => { // no information for current rule if (!catalogData[ruleId] || catalogData[ruleId].length === 0) { - return purpleAiQueryLabel; + return oobeeAiQueryLabel; } if (rulesUsingRoles.includes(ruleId)) { @@ -244,18 +244,18 @@ if (roleForHtml) { const currentLabel = `${htmlElement}_${roleForHtml}`.trim(); const foundLabel = catalogData[ruleId].find(label => label === currentLabel); - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(currentLabel) : null; + return oobeeAiQueryLabel; } } // e.g. li_aria-controls_aria-selected_role - const currentLabelList = getHtmlTagAndAttributes(purpleAiHtmlETL(ruleHtml)); + const currentLabelList = getHtmlTagAndAttributes(oobeeAiHtmlETL(ruleHtml)); const currentLabel = currentLabelList.join('_'); if (catalogData[ruleId].includes(currentLabel)) { - purpleAiQueryLabel.label = escapeHtmlForAI(currentLabel); - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = escapeHtmlForAI(currentLabel); + return oobeeAiQueryLabel; } // count the number of elements in keyArr that @@ -269,8 +269,8 @@ return attrMatch.length >= 3; }) - purpleAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; - return purpleAiQueryLabel; + oobeeAiQueryLabel.label = foundLabel ? escapeHtmlForAI(foundLabel) : null; + return oobeeAiQueryLabel; }) .catch(err => { console.error(`An error has occurred while checking if ${ruleId} needs AI query`); @@ -291,8 +291,8 @@ } const handleOfflinePurpleAi = async (ruleId, accordionDiv, html, buttonsDiv, aiErrorDiv) => { - let purpleAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); - if (purpleAiQueryLabel.hasNetworkError) { + let oobeeAiQueryLabel = await checkPurpleAiQueryLabel(ruleId, html); + if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -300,7 +300,7 @@ `This feature requires internet connection. Please try again`, ), ); - } else if (purpleAiQueryLabel.hasNetworkError) { + } else if (oobeeAiQueryLabel.hasNetworkError) { document .getElementById(aiErrorDiv) .replaceChildren( @@ -308,10 +308,10 @@ `Something went wrong. Please try again`, ), ); - } else if (!purpleAiQueryLabel.label) { + } else if (!oobeeAiQueryLabel.label) { document.getElementById(accordionDiv).innerHTML = `Processing AI suggestions, please check back later.` } else { - await getPurpleAiAnswer(ruleId, accordionDiv, purpleAiQueryLabel.label, buttonsDiv, aiErrorDiv); + await getPurpleAiAnswer(ruleId, accordionDiv, oobeeAiQueryLabel.label, buttonsDiv, aiErrorDiv); } } diff --git a/src/static/ejs/partials/summaryHeader.ejs b/src/static/ejs/partials/summaryHeader.ejs index 73ab433a..f1e9b80b 100644 --- a/src/static/ejs/partials/summaryHeader.ejs +++ b/src/static/ejs/partials/summaryHeader.ejs @@ -46,7 +46,7 @@ /> - Purple A11y Scan Summary + Oobee Scan Summary <%# diff --git a/src/static/ejs/partials/summaryMain.ejs b/src/static/ejs/partials/summaryMain.ejs index f2f99c23..c8620ac8 100644 --- a/src/static/ejs/partials/summaryMain.ejs +++ b/src/static/ejs/partials/summaryMain.ejs @@ -63,7 +63,7 @@ (Conformance Level A & AA) Success Criteria can be automatically checked so manual testing diff --git a/src/static/ejs/report.ejs b/src/static/ejs/report.ejs index 6169f39c..c41a5039 100644 --- a/src/static/ejs/report.ejs +++ b/src/static/ejs/report.ejs @@ -251,7 +251,7 @@ itemsElement.innerHTML = itemsContent; var phAppVersionElement = document.getElementById('phAppVersion'); - var versionContent = 'Oobee Desktop Version ' + scanData.phAppVersion; + var versionContent = 'Oobee Version ' + scanData.phAppVersion; phAppVersionElement.innerHTML = versionContent; var isCustomFlow = scanData.isCustomFlow; diff --git a/src/static/ejs/summary.ejs b/src/static/ejs/summary.ejs index 6757a79b..472dc8ab 100644 --- a/src/static/ejs/summary.ejs +++ b/src/static/ejs/summary.ejs @@ -3,7 +3,7 @@ - Purple A11y Scan Summary + Oobee Scan Summary - + IMPACT @@ -1594,7 +1594,7 @@
node purpleA11y-playwright-demo.js
node oobeeA11y-playwright-demo.js
npm install playwright @govtechsg/purple-hats typescript --save-dev
npm install playwright @govtechsg/oobee typescript --save-dev
src/purpleA11y-playwright-demo.ts
src/oobeeA11y-playwright-demo.ts
src/purpleA11y-playwright-dem // additional information to include in the "Scan About" section of the report const scanAboutMetadata: ScanAboutMetadata = { browser: 'Chrome (Desktop)' }; - const purpleA11y = await purpleA11yInit( + const oobeeA11y = await oobeeA11yInit( "https://govtechsg.github.io", // initial url to start scan "Demo Playwright Scan", // label for test "Your Name", @@ -610,12 +613,12 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder.
src/purpleA11y-playwright-dem async elementsToScan => await runA11yScan(elementsToScan), elementsToScan, ); - await purpleA11y.pushScanResults(scanRes); - purpleA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate purpleA11y instance. + await oobeeA11y.pushScanResults(scanRes); + oobeeA11y.testThresholds(); // test the accumulated number of issue occurrences against specified thresholds. If exceed, terminate oobeeA11y instance. }; - await page.goto('https://govtechsg.github.io/purple-banner-embeds/purple-integrated-scan-example.htm'); - await page.evaluate(purpleA11y.getScripts()); + await page.goto('https://govtechsg.github.io/oobee-banner-embeds/oobee-integrated-scan-example.htm'); + await page.evaluate(oobeeA11y.getScripts()); await runPurpleA11yScan(); await page.getByRole('button', { name: 'Click Me' }).click(); @@ -626,13 +629,13 @@ Create a sub-folder and Playwright test file src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder.
src/purpleA11y-playwright-dem // --------------------- await context.close(); await browser.close(); - await purpleA11y.terminate(); + await oobeeA11y.terminate(); })(); Compile your typescript code with npx tsc. -Run your test with node dist/purpleA11y-playwright-demo.js. +Run your test with node dist/oobeeA11y-playwright-demo.js. -You will see Purple A11y results generated in results folder. +You will see Oobee results generated in results folder.
node dist/purpleA11y-playwright-demo.js
node dist/oobeeA11y-playwright-demo.js