diff --git a/package-lock.json b/package-lock.json
index cf98e150..c2c89abc 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4125,14 +4125,6 @@
"node": ">= 10"
}
},
- "node_modules/@trysound/sax": {
- "version": "0.2.0",
- "dev": true,
- "license": "ISC",
- "engines": {
- "node": ">=10.13.0"
- }
- },
"node_modules/@types/aria-query": {
"version": "5.0.1",
"dev": true,
@@ -11372,7 +11364,9 @@
}
},
"node_modules/immutable": {
- "version": "4.1.0",
+ "version": "4.3.8",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.8.tgz",
+ "integrity": "sha512-d/Ld9aLbKpNwyl0KiM2CT1WYvkitQ1TSvmRtkcV8FKStiDoA7Slzgjmb/1G2yhKM1p0XeNOieaTbFZmU1d3Xuw==",
"dev": true,
"license": "MIT"
},
@@ -18309,6 +18303,16 @@
"node": ">=16.13.2"
}
},
+ "node_modules/sax": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.5.0.tgz",
+ "integrity": "sha512-21IYA3Q5cQf089Z6tgaUTr7lDAyzoTPx5HRtbhsME8Udispad8dC/+sziTNugOEx54ilvatQ9YCzl4KQLPcRHA==",
+ "dev": true,
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
+ },
"node_modules/saxes": {
"version": "6.0.0",
"dev": true,
@@ -19295,16 +19299,18 @@
"dev": true
},
"node_modules/svgo": {
- "version": "2.8.0",
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.2.tgz",
+ "integrity": "sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@trysound/sax": "0.2.0",
"commander": "^7.2.0",
"css-select": "^4.1.3",
"css-tree": "^1.1.3",
"csso": "^4.2.0",
"picocolors": "^1.0.0",
+ "sax": "^1.5.0",
"stable": "^0.1.8"
},
"bin": {
@@ -20117,7 +20123,9 @@
}
},
"node_modules/underscore": {
- "version": "1.13.6",
+ "version": "1.13.8",
+ "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz",
+ "integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==",
"dev": true,
"license": "MIT"
},
diff --git a/public/css/hop-styling.css b/public/css/hop-styling.css
index f6d8b552..bfe1f5f3 100644
--- a/public/css/hop-styling.css
+++ b/public/css/hop-styling.css
@@ -171,23 +171,38 @@ body .buttonContainer .btn-success:focus, body .buttonContainer .btn-success:act
background-color: #0c7e47;
box-shadow: 0 0 0 3px #ffffff, 0 0 0 5.5px #0c7e47;
}
-body .has-error input,
-body .has-error select {
+body .has-error input.form-control,
+body .has-error select.form-control {
border-color: #db0020;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+body .has-error input.form-control:focus,
+body .has-error select.form-control:focus {
+ box-shadow: none;
}
body .has-error select {
background-image: url(/icons/select-error.png);
}
body .has-error small {
+ font-size: 1rem;
+ line-height: 1.56;
margin-bottom: 0.3125rem;
color: #db0020;
}
-body .has-success input,
-body .has-success select {
+body .has-success .control-label {
+ color: #4d4e53;
+}
+body .has-success input.form-control,
+body .has-success select.form-control {
border-color: #0c7e47;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+body .has-success input.form-control:focus,
+body .has-success select.form-control:focus {
+ box-shadow: none;
}
body .has-success select {
- background-image: url(/icons/select-error.png);
+ background-image: url(/icons/select-success.png);
}
body .cc-error-container #alert-message {
background-color: #fcbfbb;
@@ -337,17 +352,6 @@ body .cc-error-container #alert-message {
}
}
-.glyphicon {
- position: relative;
- top: 1px;
- display: inline-block;
- font-family: Glyphicons Halflings;
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
-}
-
.form-control-feedback {
position: absolute;
top: 0;
@@ -361,11 +365,12 @@ body .cc-error-container #alert-message {
pointer-events: none;
top: 27px;
}
-
-.glyphicon-remove:before {
+.form-control-feedback.glyphicon {
+ display: none;
+}
+.form-control-feedback.glyphicon-remove:before {
content: "\e014";
}
-
-.glyphicon-ok:before {
+.form-control-feedback.glyphicon-ok:before {
content: "\e013";
}
diff --git a/public/css/site-2020Styling.css b/public/css/site-2020Styling.css
index 7327505d..e235fc85 100644
--- a/public/css/site-2020Styling.css
+++ b/public/css/site-2020Styling.css
@@ -4,95 +4,12 @@
/* IMPORTANT: READ README.md in this folder! Do not edit .css file directly! */
/* Style the modal when PayPal button is selected */
#pageLoadingModal {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.4);
- display: flex;
-}
-#pageLoadingModal .modal-content {
- margin: auto auto;
-}
-#pageLoadingModal p {
- margin: 0;
- text-transform: uppercase;
- font-size: 14px;
-}
-#pageLoadingModal .modal {
- display: none;
- overflow: hidden;
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- -webkit-overflow-scrolling: touch;
- outline: 0;
-}
-#pageLoadingModal .modal-content {
- position: relative;
- background-color: #fff;
- border-radius: 8px;
- background-clip: padding-box;
- outline: 0;
- width: 176px;
- height: 136px;
- display: flex;
- justify-content: center;
- align-items: center;
- background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 84 32'%3e%3cpath d='M22.39 27.313a3.53 3.53 0 0 0 7.058 0' fill='%23fff'/%3e%3cpath d='M22.39 27.313a3.53 3.53 0 0 0 7.058 0' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M54.459 27.313a3.527 3.527 0 0 0 7.054 0' fill='%23fff'/%3e%3cpath d='M54.459 27.313a3.527 3.527 0 0 0 7.054 0' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M42.06.8c8.08 0 11.89.935 11.89.935 3.58.576 5.696 7.207 5.696 7.207h.727c0-2.427 1.302-2.397 2.341-2 .723.292 1.363.76 1.86 1.361 1.319 1.547.465 1.674.465 1.674h-5.067l3.846 3.01v12.016c0 2.41-2.029 2.31-2.029 2.31H22.338s-2.029.1-2.029-2.31V12.996l3.84-3.009H19.07s-.853-.127.466-1.674a4.693 4.693 0 0 1 1.86-1.361c1.032-.397 2.341-.427 2.341 2h.736s2.117-6.64 5.696-7.21c0 0 3.81-.942 11.89-.942Z' fill='%23fff' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M42.06 8.847c7.924 0 14.685.511 14.685.511 0-2.585-2.38-6.011-2.38-6.011S50.4 2.519 42.06 2.519s-12.303.828-12.303.828-2.38 3.426-2.38 6.011c0 0 6.76-.51 14.683-.51Z' fill='%23DA291C' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M35.277 16.523a62.558 62.558 0 0 1 13.277 0m3.276-.439s2.384-2.257 8.608-2.257c0 0 1.179 2.657-2.54 3.37m-25.894-1.113s-2.387-2.257-8.611-2.257c0 0-1.16 2.579 2.543 3.37m-3.546 5.856s21.52 3.647 39.123 0' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
- background-repeat: no-repeat;
- background-position: center center;
- background-size: 96px;
-}
-#pageLoadingModal .modal-content:after {
- content: "";
- border-radius: 50%;
- position: absolute;
- width: 5.5rem;
- height: 5.5rem;
- border: 0.45em solid #d4281c;
- border-right-color: transparent;
- animation: spinnerrotate 0.75s linear infinite;
-}
-@keyframes spinnerrotate {
- 0% {
- transform: rotate(0);
- }
- 100% {
- transform: rotate(360deg);
- }
-}
-#pageLoadingModal .modal-content p {
- display: none;
-}
-#pageLoadingModal .modal-backdrop {
- position: absolute;
- top: 0;
- right: 0;
- left: 0;
- background-color: #000000;
-}
-#pageLoadingModal .modal-backdrop.fade {
- opacity: 0;
- filter: alpha(opacity=0);
-}
-#pageLoadingModal.hide {
display: none;
}
.buy-backdrop {
background-color: rgba(0, 0, 0, 0.8) !important;
}
-.buy-backdrop #afterpay__iframe-checkout-container {
- width: 100%;
-}
.buy-backdrop #afterpay__iframe-checkout-container .style_closeWrapper__lIHJe {
display: none;
}
diff --git a/public/scss/hop-styling.scss b/public/scss/hop-styling.scss
index ace72aa6..7044fdd4 100644
--- a/public/scss/hop-styling.scss
+++ b/public/scss/hop-styling.scss
@@ -198,12 +198,20 @@ body {
.has-error {
input,
select {
- border-color: #db0020;
+ &.form-control {
+ border-color: #db0020;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ &:focus {
+ box-shadow: none;
+ }
+ }
}
select {
background-image: url(/icons/select-error.png);
}
small {
+ font-size: 1rem;
+ line-height: 1.56;
margin-bottom: .3125rem;
color: #db0020;
}
@@ -211,9 +219,18 @@ body {
.has-success {
+ .control-label {
+ color: #4d4e53
+ }
input,
select {
- border-color: #0c7e47;
+ &.form-control {
+ border-color: #0c7e47;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ &:focus {
+ box-shadow: none;
+ }
+ }
}
select {
background-image: url(/icons/select-success.png);
@@ -442,17 +459,6 @@ body {
}
}
-.glyphicon {
- position: relative;
- top: 1px;
- display: inline-block;
- font-family: Glyphicons Halflings;
- font-style: normal;
- font-weight: normal;
- line-height: 1;
- -webkit-font-smoothing: antialiased;
-}
-
.form-control-feedback {
position: absolute;
top: 0;
@@ -465,10 +471,13 @@ body {
text-align: center;
pointer-events: none;
top: 27px;
-}
-.glyphicon-remove:before {
- content: "\e014";
-}
-.glyphicon-ok:before {
- content: "\e013";
+ &.glyphicon {
+ display: none;
+ }
+ &.glyphicon-remove:before {
+ content: "\e014";
+ }
+ &.glyphicon-ok:before {
+ content: "\e013";
+ }
}
\ No newline at end of file
diff --git a/public/scss/site-2020Styling.scss b/public/scss/site-2020Styling.scss
index 6ddde5dc..fe1fff81 100644
--- a/public/scss/site-2020Styling.scss
+++ b/public/scss/site-2020Styling.scss
@@ -5,89 +5,7 @@
/* Style the modal when PayPal button is selected */
#pageLoadingModal {
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- width: 100%;
- height: 100%;
- background-color: rgba(0,0,0,0.40);
- display: flex;
-
- .modal-content {
- margin: auto auto;
- }
-
- p {
- margin: 0;
- text-transform: uppercase;
- font-size: 14px;
- }
-
- .modal {
- display: none;
- overflow: hidden;
- position: fixed;
- top: 0;
- right: 0;
- bottom: 0;
- left: 0;
- z-index: 1040;
- -webkit-overflow-scrolling: touch;
- outline: 0;
- }
-
- .modal-content {
- position: relative;
- background-color: #fff;
- border-radius: 8px;
- background-clip: padding-box;
- outline: 0;
- width: 176px;
- height: 136px;
- display: flex;
- justify-content: center;
- align-items: center;
- background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 84 32'%3e%3cpath d='M22.39 27.313a3.53 3.53 0 0 0 7.058 0' fill='%23fff'/%3e%3cpath d='M22.39 27.313a3.53 3.53 0 0 0 7.058 0' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M54.459 27.313a3.527 3.527 0 0 0 7.054 0' fill='%23fff'/%3e%3cpath d='M54.459 27.313a3.527 3.527 0 0 0 7.054 0' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M42.06.8c8.08 0 11.89.935 11.89.935 3.58.576 5.696 7.207 5.696 7.207h.727c0-2.427 1.302-2.397 2.341-2 .723.292 1.363.76 1.86 1.361 1.319 1.547.465 1.674.465 1.674h-5.067l3.846 3.01v12.016c0 2.41-2.029 2.31-2.029 2.31H22.338s-2.029.1-2.029-2.31V12.996l3.84-3.009H19.07s-.853-.127.466-1.674a4.693 4.693 0 0 1 1.86-1.361c1.032-.397 2.341-.427 2.341 2h.736s2.117-6.64 5.696-7.21c0 0 3.81-.942 11.89-.942Z' fill='%23fff' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M42.06 8.847c7.924 0 14.685.511 14.685.511 0-2.585-2.38-6.011-2.38-6.011S50.4 2.519 42.06 2.519s-12.303.828-12.303.828-2.38 3.426-2.38 6.011c0 0 6.76-.51 14.683-.51Z' fill='%23DA291C' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3cpath d='M35.277 16.523a62.558 62.558 0 0 1 13.277 0m3.276-.439s2.384-2.257 8.608-2.257c0 0 1.179 2.657-2.54 3.37m-25.894-1.113s-2.387-2.257-8.611-2.257c0 0-1.16 2.579 2.543 3.37m-3.546 5.856s21.52 3.647 39.123 0' stroke='%23000' stroke-width='.75' stroke-linecap='round' stroke-linejoin='round'/%3e%3c/svg%3e");
- background-repeat: no-repeat;
- background-position: center center;
- background-size: 96px;
- &:after {
- content: '';
- border-radius: 50%;
- position: absolute;
- width: 5.5rem;
- height: 5.5rem;
- border: 0.45em solid #d4281c;
- border-right-color: transparent;
- animation: spinnerrotate 0.75s linear infinite;
- }
- @keyframes spinnerrotate {
- 0% { transform: rotate(0)}
- 100% { transform: rotate(360deg)}
- }
- p {
- display: none;
- }
- }
-
- .modal-backdrop {
- position: absolute;
- top: 0;
- right: 0;
- left: 0;
- background-color: #000000;
- &.fade {
- opacity: 0;
- filter: alpha(opacity=0);
- }
- }
-
- &.hide {
- display: none;
- }
+ display: none;
}
// AfterPay Styles
@@ -95,7 +13,6 @@
.buy-backdrop {
background-color: rgba(0,0,0,.8)!important;
#afterpay__iframe-checkout-container {
- width: 100%;
.style_closeWrapper__lIHJe {
display: none;
}
diff --git a/src/constants/component-variants.js b/src/constants/component-variants.js
index 7fd84311..d0253b6b 100644
--- a/src/constants/component-variants.js
+++ b/src/constants/component-variants.js
@@ -9,7 +9,3 @@ export const dropdownVariants = Object.freeze({
primary: 'primary',
compact: 'compact'
});
-export const modalPositions = Object.freeze({
- center: 'center',
- edge: 'edge'
-});
diff --git a/src/digital-components/modal/modal.vue b/src/digital-components/modal/modal.vue
index 83e07ccb..edb60a81 100644
--- a/src/digital-components/modal/modal.vue
+++ b/src/digital-components/modal/modal.vue
@@ -11,10 +11,7 @@
'hidden.bs.modal': onModalClosed,
'shown.bs.modal': onModalOpened
}">
-
+
@@ -68,7 +65,6 @@
import ButtonMain from '@/ux-components/button-main/button-main.vue';
import { Modal } from 'bootstrap';
import { useForm } from 'vee-validate';
-import { modalPositions } from '@/constants/component-variants';
import textLink from '@/ux-components/text-link/text-link.vue';
export default {
@@ -92,10 +88,6 @@ export default {
type: String,
default: 'success'
},
- modalPosition: {
- type: String,
- default: modalPositions.center
- },
allowInvalidSubmit: {
type: Boolean,
default: false
@@ -111,6 +103,10 @@ export default {
displayCloseLink: {
type: Boolean,
default: false
+ },
+ closeLinkText: {
+ type: String,
+ default: 'Close window'
}
},
emits: ['footer-button-event', 'isModalOpened'],
@@ -127,8 +123,7 @@ export default {
modalId,
meta,
validate,
- resetForm,
- modalPositions
+ resetForm
};
},
computed: {
@@ -186,6 +181,7 @@ export default {
right: 0;
bottom: 0;
left: 0;
+ padding-right: 1rem;
h5,
strong,
.subheader-text {
@@ -231,7 +227,8 @@ export default {
&.modal-component {
.modal-dialog {
display: flex;
- max-width: 37.5rem;
+ width: 37.5rem;
+ max-width: unset;
min-height: auto;
.modal-content {
box-shadow: 0px 1rem 3rem -1rem rgba(0, 0, 0, 0.25);
@@ -240,7 +237,7 @@ export default {
overflow: auto;
}
.modal-content {
- margin: 1.5rem auto 0 auto;
+ margin: 0 auto;
.modal-body {
padding: 0 1.5rem 0 1.5rem;
.col {
@@ -272,18 +269,10 @@ export default {
}
}
}
- &.modal-dialog-centered {
- .modal-content {
- box-shadow: 0px 1rem 3rem -1rem rgba(0, 0, 0, 0.25);
- border: 1px solid;
- border-radius: 5px;
- overflow: auto;
- }
- }
}
.modal-footer {
border-top: none;
- padding: 10px 1.5rem 1.5rem 1.5rem;
+ padding: .625rem 1.5rem 1.5rem 1.5rem;
button {
margin: 0;
@@ -303,6 +292,15 @@ export default {
transition: opacity 0.25s linear;
}
}
+ @include media-breakpoint-down(md) {
+ &.modal-component {
+ .modal-dialog {
+ width: auto;
+ max-width: unset;
+ margin: .625rem;
+ }
+ }
+ }
}
body {
.modal-backdrop {
diff --git a/src/iss-components/contact-details-drawer/__snapshots__/contact-details-drawer.spec.js.snap b/src/iss-components/contact-details-drawer/__snapshots__/contact-details-drawer.spec.js.snap
index effbe1a8..c73e8e9e 100644
--- a/src/iss-components/contact-details-drawer/__snapshots__/contact-details-drawer.spec.js.snap
+++ b/src/iss-components/contact-details-drawer/__snapshots__/contact-details-drawer.spec.js.snap
@@ -8,10 +8,6 @@ Object {
"firstName": "Frederick",
"isModalOpened": false,
"lastName": "Taylor",
- "modalPositions": Object {
- "center": "center",
- "edge": "edge",
- },
"phoneNumber": "606-009-2943",
"rules": Object {
"emailAddress": "email-required|email-address-format",
diff --git a/src/iss-components/contact-details-drawer/contact-details-drawer.vue b/src/iss-components/contact-details-drawer/contact-details-drawer.vue
index 660ae1c3..0c977bf9 100644
--- a/src/iss-components/contact-details-drawer/contact-details-drawer.vue
+++ b/src/iss-components/contact-details-drawer/contact-details-drawer.vue
@@ -1,15 +1,16 @@
- {{ nameSectionLabel }}
+ {{ nameSectionLabel }}
@@ -58,7 +63,7 @@ export default {
},
modalSubHeaderText() {
return this.getCmsContent('ContinueReferralModalWidget', 'SubheaderText')
- .replaceAll('{custom:mmFound}', this.getMakeModelString);
+ .replaceAll('{custom:mmFound}', this.getMakeModelString.toUpperCase());
}
},
methods: {
@@ -82,5 +87,64 @@ export default {
diff --git a/src/iss-components/loading-modal/loading-modal.vue b/src/iss-components/loading-modal/loading-modal.vue
index e8303824..602ea77b 100644
--- a/src/iss-components/loading-modal/loading-modal.vue
+++ b/src/iss-components/loading-modal/loading-modal.vue
@@ -124,13 +124,7 @@ export default {
justify-content: flex-start;
align-items: center;
flex-direction: column;
- @include media-breakpoint-up(xs) {
- padding-top: 5rem;
- }
-
- @include media-breakpoint-up(md) {
- padding-top: 7rem;
- }
+ padding: 2rem;
.modal-loader-content-container {
min-width: 15rem; // 240px
diff --git a/src/layouts/contact-details/contact-details.spec.js b/src/layouts/contact-details/contact-details.spec.js
index 8a4d4d7b..6d1be304 100644
--- a/src/layouts/contact-details/contact-details.spec.js
+++ b/src/layouts/contact-details/contact-details.spec.js
@@ -10,11 +10,69 @@ import { getRandomString, getRandomInt, getRandomBoolean } from '@/helpers/data-
import navigationScenarios from '@/router/router-constants/navigation-scenarios.js';
import { useMainStore } from '@/store/index.js';
+/** @ignore */
+function setupMocks({
+ storeData,
+ props
+}) {
+ const mountOptions = getMountOptions({
+ router: {
+ navigate: jest.fn(),
+ navigateWithSpinner: jest.fn()
+ },
+ loadScript: jest.fn().mockResolvedValue()
+ });
+
+ if (storeData) mountOptions.global.plugins = [createTestingPinia({
+ initialState: {
+ main: storeData
+ }
+ })];
+
+ window.google = {
+ maps: {
+ event: {
+ addListener: jest
+ .fn()
+ .mockImplementation((element, eventName, callbackFunction) => {
+ /** @ignore */
+ function interceptedCallbackFunction(e) {
+ callbackFunction(e.detail);
+ }
+ // selectedPlace = "Woogly";
+ element.addEventListener(eventName, interceptedCallbackFunction);
+ }),
+ removeListener: jest.fn(),
+ clearInstanceListeners: jest.fn()
+ },
+ places: {
+ Autocomplete: jest.fn().mockImplementation((el) => el),
+ AutocompleteService: jest.fn().mockImplementation(() => {
+ return {
+ getPlacePredictions: (request, callback) => {
+ // Throwing an error here guarantees that the function that calls it finishes
+ throw new Error();
+ }
+ };
+ }),
+ PlacesService: jest.fn().mockImplementation(() => {}),
+ AutocompleteSessionToken: jest.fn().mockImplementation(() => {})
+ }
+ }
+ };
+
+ if (props) mountOptions.propsData = props;
+
+ const wrapper = shallowMount(contactDetails, mountOptions);
+
+ return { wrapper };
+}
+
describe('contactDetails.vue', () => {
describe('Rendering', () => {
test('Should render site header', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const siteHeader = wrapper.findComponent({ ref: 'siteHeader' });
@@ -24,7 +82,7 @@ describe('contactDetails.vue', () => {
});
test('Should render sub title', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const siteSubHeader = wrapper.findComponent({ ref: 'siteSubHeader' });
@@ -34,7 +92,7 @@ describe('contactDetails.vue', () => {
});
test('Should render appointment information alert', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const appointmentInformationAlert = wrapper.findComponent({ ref: 'appointmentInformationAlert' });
@@ -44,8 +102,6 @@ describe('contactDetails.vue', () => {
});
test('Should render same as policy address question subcomponent if service zip is same as customer zip', async () => {
// Arrange
- const mountOptions = getMountOptions();
-
const customerStreetAddress = getRandomString(10, 50);
const customerStreetAddress2 = getRandomString(0, 50);
const customerCity = getRandomString(4, 20);
@@ -55,7 +111,7 @@ describe('contactDetails.vue', () => {
const serviceCity = getRandomString(4, 20);
const serviceState = getRandomString(2, 2);
const zipCode = getRandomInt(10000, 99999).toString();
- const mainInitialState = {
+ const storeData = {
order: {
customer: {
address: {
@@ -75,12 +131,7 @@ describe('contactDetails.vue', () => {
}
}
};
- mountOptions.global.plugins = [createTestingPinia({
- initialState: {
- main: mainInitialState
- }
- })];
- const wrapper = shallowMount(contactDetails, mountOptions);
+ const { wrapper } = setupMocks({ storeData });
await wrapper.vm.$nextTick();
@@ -92,8 +143,6 @@ describe('contactDetails.vue', () => {
});
test('Should not render same as policy address question subcomponent if service zip is different from customer zip', () => {
// Arrange
- const mountOptions = getMountOptions();
-
const firstName = getRandomString(4, 15);
const lastName = getRandomString(4, 15);
const emailAddress = getRandomString(10, 20);
@@ -101,7 +150,7 @@ describe('contactDetails.vue', () => {
const testZipCode = getRandomInt(10000, 99999);
const customerZipCode = testZipCode.toString();
const serviceZipCode = (testZipCode + 1).toString();
- const mainInitialState = {
+ const storeData = {
order: {
customer: {
firstName,
@@ -119,12 +168,7 @@ describe('contactDetails.vue', () => {
}
}
};
- mountOptions.global.plugins = [createTestingPinia({
- initialState: {
- main: mainInitialState
- }
- })];
- const wrapper = shallowMount(contactDetails, mountOptions);
+ const { wrapper } = setupMocks({ storeData });
// Act
const sameAsPolicyAddressQuestion = wrapper.findComponent({ ref: 'sameAsPolicyAddressQuestion' });
@@ -134,7 +178,7 @@ describe('contactDetails.vue', () => {
});
test('Should render address question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const addressQuestion = wrapper.findComponent({ ref: 'addressQuestion' });
@@ -144,7 +188,7 @@ describe('contactDetails.vue', () => {
});
test('Should render apartment question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const address2Question = wrapper.findComponent({ ref: 'address2Question' });
@@ -154,7 +198,7 @@ describe('contactDetails.vue', () => {
});
test('Should render city question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const cityQuestion = wrapper.findComponent({ ref: 'cityQuestion' });
@@ -164,7 +208,7 @@ describe('contactDetails.vue', () => {
});
test('Should render state question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const stateQuestion = wrapper.findComponent({ ref: 'stateQuestion' });
@@ -174,7 +218,7 @@ describe('contactDetails.vue', () => {
});
test('Should render zip code question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const zipCodeQuestion = wrapper.findComponent({ ref: 'zipCodeQuestion' });
@@ -184,7 +228,7 @@ describe('contactDetails.vue', () => {
});
test('Should render change zip code alert', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const changeZipCodeAlert = wrapper.findComponent({ ref: 'changeZipCodeAlert' });
@@ -194,7 +238,7 @@ describe('contactDetails.vue', () => {
});
test('Should render vehicle protected question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const vehicleProtectedQuestion = wrapper.findComponent({ ref: 'vehicleProtectedQuestion' });
@@ -204,7 +248,7 @@ describe('contactDetails.vue', () => {
});
test('Should render technician notes textarea question subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const notesQuestion = wrapper.findComponent({ ref: 'notesQuestion' });
@@ -214,7 +258,7 @@ describe('contactDetails.vue', () => {
});
test('Should render clearance text subcomponent', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const clearanceText = wrapper.findComponent({ ref: 'clearanceText' });
@@ -224,7 +268,7 @@ describe('contactDetails.vue', () => {
});
test('Should render site footer', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions());
+ const { wrapper } = setupMocks({});
// Act
const footer = wrapper.findComponent({ ref: 'siteFooter' });
@@ -234,8 +278,6 @@ describe('contactDetails.vue', () => {
});
test('Mocked store yields expected data', () => {
// Arrange
- const mountOptions = getMountOptions();
-
const address = getRandomString(10, 50);
const address2 = getRandomString(0, 50);
const city = getRandomString(4, 20);
@@ -243,7 +285,7 @@ describe('contactDetails.vue', () => {
const zipCode = getRandomInt(10000, 99999).toString();
const notesForTechnician = getRandomString(1, 100);
const isVehicleProtected = getRandomBoolean();
- const mainInitialState = {
+ const storeData = {
order: {
serviceLocation: {
address,
@@ -258,13 +300,8 @@ describe('contactDetails.vue', () => {
}
}
};
- mountOptions.global.plugins = [createTestingPinia({
- initialState: {
- main: mainInitialState
- }
- })];
- const wrapper = shallowMount(contactDetails, mountOptions);
+ const { wrapper } = setupMocks({ storeData });
// Assert
expect(wrapper.vm.address).toBe(address);
@@ -280,11 +317,7 @@ describe('contactDetails.vue', () => {
describe('Navigation', () => {
test('Back button clicked triggers navigation', () => {
// Arrange
- const wrapper = shallowMount(contactDetails, getMountOptions({
- router: {
- navigateWithSpinner: jest.fn()
- }
- }));
+ const { wrapper } = setupMocks({});
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
// Act
@@ -295,41 +328,25 @@ describe('contactDetails.vue', () => {
expect(wrapper.vm.$router.navigateWithSpinner)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, undefined);
});
- test('Forward button clicked triggers appropriate navigation', () => {
+ test('Forward button clicked triggers appropriate navigation', async () => {
// Arrange
- const mountOptions = getMountOptions({
- router: {
- navigate: jest.fn()
- },
- navigationScenarios
- });
- const mainInitialState = {
+ const storeData = {
order: {
serviceLocation: { IsSafeliteProvider: true }
}
};
- mountOptions.global.plugins = [createTestingPinia({
- initialState: {
- main: mainInitialState
- }
- })];
- const wrapper = shallowMount(contactDetails, mountOptions);
+ const { wrapper } = setupMocks({ storeData });
// Act
- wrapper.vm.forwardButtonAction();
+ await wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
expect(wrapper.vm.$router.navigate)
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined);
});
- test('Forward button click updates service location info', () => {
+ test('Forward button click updates service location info', async () => {
// Arrange
- const mountOptions = getMountOptions({
- router: {
- navigate: jest.fn()
- }
- });
const provider = {
address: {
city: getRandomString(4, 20),
@@ -342,19 +359,14 @@ describe('contactDetails.vue', () => {
phoneNumber: getRandomInt(1000000000, 9999999999).toString(),
providerNumber: getRandomInt(100000, 999999).toString()
}
- const mainInitialState = {
+ const storeData = {
order: {
serviceLocation: {
provider
}
}
};
- mountOptions.global.plugins = [createTestingPinia({
- initialState: {
- main: mainInitialState
- }
- })];
- const wrapper = shallowMount(contactDetails, mountOptions);
+ const { wrapper } = setupMocks({ storeData });
const address = getRandomString(10, 50);
const address2 = getRandomString(0, 50);
const city = getRandomString(4, 20);
@@ -371,7 +383,7 @@ describe('contactDetails.vue', () => {
});
// Act
- wrapper.vm.forwardButtonAction();
+ await wrapper.vm.forwardButtonAction();
// Assert
expect(useMainStore().updateServiceLocation).toHaveBeenCalledWith({
@@ -383,21 +395,16 @@ describe('contactDetails.vue', () => {
});
});
- test('Forward button click updates notes for technician', () => {
+ test('Forward button click updates notes for technician', async () => {
// Arrange
- const mountOptions = getMountOptions({
- router: {
- navigate: jest.fn()
- }
- });
- const wrapper = shallowMount(contactDetails, mountOptions);
+ const { wrapper } = setupMocks({});
const notesForTechnician = getRandomString(1, 100);
wrapper.setData({
notesForTechnician
});
// Act
- wrapper.vm.forwardButtonAction();
+ await wrapper.vm.forwardButtonAction();
// Assert
expect(useMainStore().updateContactInfo).toHaveBeenCalledWith({
diff --git a/src/layouts/contact-details/contact-details.vue b/src/layouts/contact-details/contact-details.vue
index b864ff19..b73d3fc4 100644
--- a/src/layouts/contact-details/contact-details.vue
+++ b/src/layouts/contact-details/contact-details.vue
@@ -133,6 +133,7 @@ import errorMessages from '@/constants/error-messages';
import { required } from '@/helpers/validation-rules';
import widgetFields from '@/constants/cms-widget-fields';
import states from '@/constants/states';
+import applicationConfig from '@/constants/application-config';
// DEFINE VALIDATION RULES
defineRule('street-address-required', required(errorMessages.SERVICE_ADDRESS_REQUIRED));
@@ -157,8 +158,9 @@ export default {
async beforeRouteEnter(to, from, next) {
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
- next((vm) => {
+ next(async (vm) => {
vm.setCmsContent(cmsContent);
+ await vm.setupAddressLookup();
});
},
data() {
@@ -239,7 +241,7 @@ export default {
/**
* @summary Steps to perform when forward button clicked.
*/
- forwardButtonAction() {
+ async forwardButtonAction() {
const contactInfo = {
notesForTechnician: this.notesForTechnician
};
@@ -247,6 +249,8 @@ export default {
const provider = useMainStore().serviceLocation.provider;
+ await this.geocodeAddress();
+
useMainStore().updateServiceLocation({
address: this.address,
address2: this.address2,
@@ -267,7 +271,100 @@ export default {
this.address = '';
this.address2 = '';
this.city = '';
- }
+ },
+ async setupAddressLookup() {
+ const apiKey = applicationConfig.GOOGLE_PLACES_API_KEY;
+
+ await this.$loadScript(`https://maps.googleapis.com/maps/api/js?key=${apiKey}&libraries=places&callback=Function.prototype`)
+ .catch(() => {
+ // Failed to fetch script
+ window.console.warn('Unable to load Google Places API script');
+ });
+ },
+ geocodeAddress() {
+ const autoCompletePromise = new Promise((resolve, reject) => {
+ try {
+ // Get Autocomplete Service
+ const acService = new window.google.maps.places.AutocompleteService();
+ // Get Places Service, needs pseudo element (or a map)
+ const placeService = new window.google.maps.places.PlacesService(document.createElement('div'));
+ // Create Autocomplete Session token, multiple requests one pricing hit
+ const acSessionToken = new window.google.maps.places.AutocompleteSessionToken();
+
+ const addressValue = `${this.address}, ${this.city}, ${this.state} ${this.zipCode}`;
+ acService.getPlacePredictions(
+ {
+ input: addressValue,
+ type: ['geocode'],
+ componentRestrictions: { country: ['us'] },
+ sessionToken: acSessionToken
+ },
+ (predictions) => {
+ if (predictions && predictions.length > 0) {
+ const firstPrediction = predictions[0];
+ if (firstPrediction.place_id) {
+ placeService.getDetails(
+ {
+ placeId: firstPrediction.place_id,
+ fields: ['address_components'],
+ sessionToken: acSessionToken
+ },
+ (details) => {
+ this.fillInAddress(details);
+ resolve();
+ }
+ );
+ } else {
+ resolve();
+ }
+ } else {
+ resolve();
+ }
+ }
+ );
+ } catch (error) {
+ window.console.warn('Error initializing Google Places API services', error);
+ resolve();
+ }
+ });
+
+ return autoCompletePromise;
+ },
+ async fillInAddress(googlePlace) {
+ let processedStreetAddress = false;
+ let processedRoute = false;
+ for (const component of googlePlace.address_components) {
+ const componentType = component.types[0];
+
+ switch (componentType) {
+ case 'street_number': {
+ if (processedRoute) {
+ this.address = `${component.long_name} ${this.address}`;
+ } else {
+ this.address = component.long_name;
+ }
+
+ processedStreetAddress = true;
+ break;
+ }
+ case 'route': {
+ if (processedStreetAddress) {
+ this.address += ` ${component.short_name}`;
+ } else {
+ this.address = component.short_name;
+ }
+
+ processedRoute = true;
+ break;
+ }
+ case 'locality': {
+ this.city = component.long_name;
+ break;
+ }
+ default:
+ }
+ }
+ },
}
};
diff --git a/src/layouts/payment-method/payment-method.vue b/src/layouts/payment-method/payment-method.vue
index 90144474..41eee5ee 100644
--- a/src/layouts/payment-method/payment-method.vue
+++ b/src/layouts/payment-method/payment-method.vue
@@ -389,7 +389,6 @@ export default {
}
this.smsPhoneNumber = this.getSMSPhoneFromStore();
if (this.isPayInAdvanceDisabled) {
- console.log('Pay in Advance is disabled, defaulting to Pay at Time of Service');
this.paymentMethod = paymentMethods.PAY_AT_TIME_OF_SERVICE;
}
},
@@ -442,8 +441,11 @@ export default {
handleEditClicked(section) {
switch (section) {
case 'location':
+ const scenario = this.mainStore.isMobileAppointment
+ ? this.navigationScenarios.EDIT_SERVICE_LOCATION_MOBILE
+ : this.navigationScenarios.EDIT_SERVICE_LOCATION_INSHOP;
this.$router.navigateWithSpinner(
- this.navigationScenarios.EDIT_SERVICE_LOCATION,
+ scenario,
this.$route
);
break;
diff --git a/src/layouts/payment-page/payment-page.vue b/src/layouts/payment-page/payment-page.vue
index 4d307e34..d116b502 100644
--- a/src/layouts/payment-page/payment-page.vue
+++ b/src/layouts/payment-page/payment-page.vue
@@ -470,7 +470,7 @@ export default {
const paymentType = useMainStore().order.payment.paymentMethod;
const alertToDisplay = to.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT];
if (paymentType === paymentMethods.PAYPAL || alertToDisplay) {
- useMainStore().savePaymentMethodChoice(paymentMethods.CREDIT_CARD);
+ useMainStore().savePaymentMethodChoice(paymentMethods.PayNow);
}
// Call APIs
@@ -535,7 +535,9 @@ export default {
displayAmount: this.getDisplayAmountDue(),
payInAdvanceLineItems: '',
shouldBlockInteraction: false,
- afterpayModalOpen: false
+ afterpayModalOpen: false,
+ iframeLoaded: false,
+ iframeResizerLoaded: false
};
},
computed: {
@@ -776,6 +778,7 @@ export default {
} else {
iframe.contentWindow.postMessage('CreditCardChosen', '*');
}
+ this.iframeLoaded = true;
}
};
}
@@ -788,6 +791,7 @@ export default {
}
if (event.data.includes('afterpayClosed')) {
+ this.allowIFrameResize(iframe);
if (this.isAfterPay) {
this.backButtonAction();
} else {
@@ -810,7 +814,6 @@ export default {
useMainStore().savePaymentMethodChoice(paymentMethods.AFTERPAY);
}
if (event.data.includes('applepayOpened')) {
- this.showIssLoadingModal(true);
useMainStore().savePaymentMethodChoice(paymentMethods.APPLEPAY);
}
if (event.data.includes('showLoaderForPaypal')) {
@@ -855,17 +858,28 @@ export default {
},
submitPaymentAction() {
const iframe = this.$refs.paymentFrame;
- if (iframe && iframe.contentWindow) {
+ if (iframe && iframe.contentWindow && this.iframeLoaded) {
iframe.contentWindow.postMessage('submitPayment', '*');
}
},
switchToAfterPay() {
const iframe = this.$refs.paymentFrame;
- if (iframe && iframe.contentWindow) {
+ if (iframe && iframe.contentWindow && this.iframeLoaded) {
this.afterpayModalOpen = true;
+ this.lockIFrameSize(iframe);
iframe.contentWindow.postMessage('afterpay-switch', '*');
}
},
+ lockIFrameSize(iframe) {
+ if (iframe && iframe.iFrameResizer) {
+ iframe.iFrameResizer.removeListeners();
+ }
+ },
+ allowIFrameResize(iframe) {
+ if (iframe) {
+ iframeResize({ checkOrigin: false }, iframe);
+ }
+ },
showIssLoadingModal
}
};
diff --git a/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue b/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue
index 52190077..5e295340 100644
--- a/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue
+++ b/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue
@@ -9,7 +9,7 @@
:displayCloseButton="false"
:displayCloseLink="true">
@@ -122,7 +121,6 @@ import {
import { submitWorkOrder } from '@/helpers/order-helper.js';
import bailoutMessage from '@/constants/bailoutMessage';
import submitType from '@/constants/submit-type';
-import { modalPositions } from '@/constants/component-variants';
const VERIFYING_COVERAGE = 'Verifying coverage';
@@ -159,8 +157,7 @@ export default {
alertRecalWarning: 'AlertRecalWarningWidget',
editShopLinkText: 'EditShopLinkTextWidget',
contactDetails: 'ContactDetailsSectionWidget'
- },
- modalPositions
+ }
};
},
computed: {
@@ -345,7 +342,7 @@ export default {
}
};
-