Merge pull request #1166 from Safelite/feature/jnou/INSR-6847

Feature/jnou/insr 6847
This commit is contained in:
JennyNou 2026-04-03 12:32:18 -04:00 committed by GitHub
commit 9ef978b29b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
47 changed files with 315 additions and 474 deletions

View file

@ -11,6 +11,11 @@ COPY package*.json ./
# Install dependencies
RUN npm install
# Copy playwright-tests package files + authenticated .npmrc, then install
COPY playwright-tests/package*.json ./playwright-tests/
COPY playwright-tests/.npmrc ./playwright-tests/
RUN cd playwright-tests && npm install
# Install Playwright browsers
RUN npx playwright install chromium --with-deps

View file

@ -46,7 +46,7 @@ stages:
targetUrl: $(BASE_URL)
dockerFileName: 'Dockerfile.playwright'
isRegression: ${{ variables.IS_REGRESSION }}
filterTags: '@Advanced'
filterTags: 'Liberty Mutual'
playwrightTestsPath: 'playwright-tests'
npmServePath: '.'
npmrcPath: 'playwright-tests/.npmrc'

View file

@ -28,17 +28,12 @@ resources:
type: github
name: Safelite/AzureDevOps
endpoint: Safelite
ref: refs/tags/t5.5.40
ref: refs/tags/t5.7.53
variables:
- group: Digital-Infrastructure
- group: ISS-BuildBranches
- name: dockerImageName
value: 'playwright-tests'
- name: imageTag
value: '$(Build.BuildId)'
- name: totalShards
value: 2
- group: SafelitePlaywright
- name: IS_REGRESSION
value: 'false'
@ -54,170 +49,20 @@ stages:
npmLocation: $(Build.SourcesDirectory)
testResultsFile: junit.xml
summaryFileLocation: $(Build.SourcesDirectory)/coverage/cobertura-coverage.xml
- job: playwright_tests
continueOnError: true
strategy:
matrix:
shard1:
shardNumber: 1
shard2:
shardNumber: 2
# shard3:
# shardNumber: 3
# shard4:
# shardNumber: 4
steps:
- task: Docker@2
displayName: 'Build Docker Image'
inputs:
command: build
dockerfile: Dockerfile.playwright
repository: $(dockerImageName)
tags: $(imageTag)
arguments: '--no-cache --pull'
- script: |
branch_name=$(System.PullRequest.SourceBranch)
echo "Retrieved branch name: '$branch_name'"
JIRA_CARD_NUMBER="${branch_name##*/}"
echo "Extracted JIRA Card number: '$JIRA_CARD_NUMBER'"
# Create container and run tests
container_id=$(docker create \
--ipc=host \
-e CCIS_API_AUTH=$(CCIS_API_AUTH) \
-e BASE_URL=$(BASE_URL) \
-e CCIS_API_URL=$(CCIS_API_URL) \
-e ADMIN_SERVICE_API_URL=$(ADMIN_SERVICE_API_URL) \
-e SHARD=$(shardNumber) \
-e CI=true \
-e ENABLE_MOCK_TESTING=true \
-e ENABLE_ACCESSIBILITY_TESTING=true \
-e NODE_ENV=$(NODE_ENV) \
$(dockerImageName):$(imageTag) \
npx concurrently -k -n "server,playwright"\
"sed -i \"s|^process\.env\.VUE_APP_CONSUMER_CF_DISTRO = .*|process\.env\.VUE_APP_CONSUMER_CF_DISTRO='https://digitalapi.test.safelite.io'|\" \"./vue.config.js\" && echo \"Updated config file to use TEST APIs\" && npm run serve -- --port=8080"\
"npx wait-on http://localhost:8080 && npm run test:playwright -- --shard=$(shardNumber)/$(totalShards) --reporter=list,blob --grep \"@$JIRA_CARD_NUMBER\"")
# Start container and stream logs
echo "Starting tests for shard $(shardNumber)..."
docker start -a $container_id
# Create directory for test results
echo "Creating test results directory..."
mkdir -p $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)
# Copy test results from container
echo "Copying test results..."
docker cp $container_id:/app/blob-report/. $(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)/
# Remove container
echo "Cleaning up container..."
docker rm $container_id
# Check if tests failed
if [ $? -ne 0 ]; then
echo "Tests failed in shard $(shardNumber) or tests don't exist for this shard number!"
exit 0 # Suppress error. It will be visible in report.
fi
displayName: 'Run Playwright Tests - Shard $(shardNumber)'
- task: PublishPipelineArtifact@1
displayName: 'Publish Test Reports - Shard $(shardNumber)'
condition: always()
inputs:
targetPath: '$(System.DefaultWorkingDirectory)/blob-reports/shard-$(shardNumber)'
artifact: 'playwright-report-shard-$(shardNumber)'
publishLocation: 'pipeline'
- script: |
docker rmi $(dockerImageName):$(imageTag) -f
displayName: 'Cleanup Docker Image'
condition: always()
- job: download_and_merge_reports
dependsOn: playwright_tests
timeoutInMinutes: 10
cancelTimeoutInMinutes: 10
steps:
- task: DownloadPipelineArtifact@2
inputs:
targetPath: '$(System.DefaultWorkingDirectory)/playwright-reports'
- task: Docker@2
displayName: 'Build Docker Image'
inputs:
command: build
dockerfile: Dockerfile.playwright
repository: $(dockerImageName)
tags: $(imageTag)
arguments: '--no-cache --pull'
- bash: |
branch_name=$(System.PullRequest.SourceBranch)
echo "Retrieved branch name: '$branch_name'"
JIRA_CARD_NUMBER="${branch_name##*/}"
echo "Extracted JIRA Card number: '$JIRA_CARD_NUMBER'"
# Create container for jira writeback
container_id=$(docker create \
--ipc=host \
-e JIRA_SERVER=$(JIRA_SERVER) \
-e JIRA_USERNAME=$(JIRA_USERNAME) \
-e JIRA_API_KEY=$(JIRA_API_KEY) \
-e IS_REGRESSION=$(IS_REGRESSION) \
-e JIRA_CARD_NUMBER="$JIRA_CARD_NUMBER" \
$(dockerImageName):$(imageTag) \
bash -c "echo \"Moving Playwright reports out of subfolders...\" &&
find ./playwright-reports/ -mindepth 2 -type f -exec mv {} ./playwright-reports/ \; &&
echo \"Merging reports...\" &&
export NODE_OPTIONS=--max_old_space_size=4096
PLAYWRIGHT_JUNIT_OUTPUT_DIR='/app/test-results' PLAYWRIGHT_JUNIT_OUTPUT_NAME='junit_results.xml' npx playwright merge-reports --reporter=junit,\"/app/playwright-tests/impl/reporter/JiraWritebackReporter.ts\" ./playwright-reports
echo \"Contents of ortoni-report:\" && ls ./ortoni-report &&
echo 'Current dir: ' && pwd
echo 'Contents of current dir: ' && ls
echo 'Contents of /app/test-results' && ls /app/test-results ")
# Start container and stream logs
echo "Starting merge"
docker start -a $container_id
# Create directory for test results
echo "Creating test results directory..."
mkdir -p $(System.DefaultWorkingDirectory)/ortoni-report
mkdir -p $(System.DefaultWorkingDirectory)/test-results
# Copy test results from container
echo "Copying test results..."
docker cp $container_id:/app/ortoni-report/. $(System.DefaultWorkingDirectory)/ortoni-report
docker cp $container_id:/app/test-results/junit_results.xml $(System.DefaultWorkingDirectory)/test-results
# Remove container
echo "Cleaning up container..."
docker rm $container_id
env:
- template: templates/digital/playwright-test.yml@AzureDevOps
parameters:
applicationType: 'vue'
totalShards: 2
targetUrl: $(BASE_URL)
dockerFileName: 'Dockerfile.playwright'
isRegression: false
filterTags: ''
playwrightTestsPath: 'playwright-tests'
npmServePath: '.'
npmrcPath: 'playwright-tests/.npmrc'
secrets:
CCIS_API_AUTH: $(CCIS_API_AUTH)
JIRA_API_KEY: $(JIRA_API_KEY)
displayName: merge_and_publish_results_to_jira
- task: PublishTestResults@2
displayName: 'Publish test results'
inputs:
searchFolder: 'test-results'
testResultsFormat: 'JUnit'
testResultsFiles: 'junit_results.xml'
mergeTestResults: true
failTaskOnFailedTests: false
testRunTitle: 'Playwright Tests'
condition: succeededOrFailed()
- task: PublishPipelineArtifact@1
displayName: 'Publish Merged Report'
condition: always()
inputs:
targetPath: '$(System.DefaultWorkingDirectory)/ortoni-report'
artifact: 'playwright-merged-report'
publishLocation: 'pipeline'
- script: |
docker rmi $(dockerImageName):$(imageTag) -f
displayName: 'Cleanup Docker Image'
condition: always()
- ${{ else }}:
# Dev Build/Deploy

View file

@ -37,6 +37,12 @@ export interface IVehicleDetails {
vehicleLookupType?: VehicleLookupType,
}
export interface IAddressVehicleDetails {
year: string,
make: string,
model: string,
}
export interface IAppointmentDetails {
serviceLocation: ServiceLocation,
appointmentDate?: Date,

View file

@ -8,5 +8,6 @@ export default interface IBailoutFlags {
isVehicleLookupBailout: boolean,
isPriceServiceErrorBailout: boolean,
isCoverageCancelledByUser: boolean,
isAPIErrorBailout: boolean
isAPIErrorBailout: boolean,
isBailoutAfterVinLookup: boolean,
}

View file

@ -1,5 +1,5 @@
import { ServicePackage, VehicleDamage } from "./Enums"
import { IAppointmentDetails, IClaimDetails, ICustomerDetails, IEndorsementDetails, IPartQuestion, IPaymentDetails, IVehicleDetails } from "./CustomerDetails"
import { IAppointmentDetails, IClaimDetails, ICustomerDetails, IEndorsementDetails, IPartQuestion, IPaymentDetails, IVehicleDetails, IAddressVehicleDetails } from "./CustomerDetails"
import IBailoutFlags from "./IBailoutFlags"
export interface ITestData {
@ -8,7 +8,8 @@ export interface ITestData {
isDuplicateClaim: boolean,
isPolicyFound: boolean, // Effective difference between advanced and essential
isUnverifiedPolicyAfterVehicleLookup: boolean, // Changing license plate can cause flow to change to unverified from verified
isUseVehicleOnPolicy: boolean, // Should we use the vehicle on the policy?
isUseVehicleOnPolicy: boolean,
isUseVehicleFromAddressLookup: boolean, // Should we use the vehicle from the address lookup?
isVehicleLookupValidations: boolean, // Should we validate vehicle lookup?
isAddressLookupValidations: boolean, // Should we validate address lookup errors?
isVehicleSelectBailout: boolean, // Should we bailout on vehicle lookup?
@ -29,6 +30,7 @@ export interface ITestData {
customerDetails: ICustomerDetails,
claimDetails: IClaimDetails,
vehicleDetails: IVehicleDetails,
addressVehicleDetails: IAddressVehicleDetails,
editVehicleDetails: IVehicleDetails, // Vehicle details entered after clicking "Edit vehicle" on Vehicle Details page
otherVehiclesOnPolicy: IVehicleDetails[], // IF defined, we validate that the vehicles are present.
vehicleDamage: VehicleDamage[], // Array of vehicle damage
@ -36,6 +38,7 @@ export interface ITestData {
paymentDetails: IPaymentDetails // Payment information
isRecalNotification: boolean,
isRecalWarning: boolean,
isRecalVehicle: boolean,
isSeparateApptsWarning: boolean, // IF true, check for the separate appts warning on VehicleDamagePage
isAuthenticationRequired: boolean,
isMoldingQuestion: boolean,

View file

@ -1,4 +1,5 @@
import { AddressLookupPage } from "../../pages/AddressLookupPage";
import { AddressVehiclesPage } from "../../pages/AddressVehiclesPage";
import { BailoutPage } from "../../pages/BailoutPage";
import CapabilityQuestionsPage from "../../pages/CapabilityQuestionsPage";
import { ContactConfirmationPage } from "../../pages/ContactConfirmationPage";
@ -31,6 +32,8 @@ import { VinLookupPage } from "../../pages/VinLookupPage";
import { WelcomePage } from "../../pages/WelcomePage";
export default interface ITestPages {
addressLookupPage: AddressLookupPage,
addressVehiclesPage: AddressVehiclesPage,
bailoutPage: BailoutPage,
capabilityQuestionsPage: CapabilityQuestionsPage,
contactConfirmationPage: ContactConfirmationPage,
@ -61,5 +64,4 @@ export default interface ITestPages {
vehicleLookupLicensePage: VehicleLookupLicensePage,
welcomePage: WelcomePage,
moldingQuestionsPage: MoldingQuestionsPage,
addressLookupPage: AddressLookupPage,
}

View file

@ -45,6 +45,7 @@ import VehiclePartQuestionsPage from "../../pages/VehiclePartsPage";
import CapabilityQuestionsPage from "../../pages/CapabilityQuestionsPage";
import { MoldingQuestionsPage } from "../../pages/MoldingQuestionsPage";
import { AddressLookupPage } from "../../pages/AddressLookupPage";
import { AddressVehiclesPage } from "../../pages/AddressVehiclesPage";
export default class TestCase extends DisposableBase implements ITestCase {
public static FrameworkConfig: FrameworkConfig = {
@ -177,6 +178,8 @@ export default class TestCase extends DisposableBase implements ITestCase {
public setupPages(page: Page): void {
this.pages = {
addressLookupPage: new AddressLookupPage(page),
addressVehiclesPage: new AddressVehiclesPage(page),
bailoutPage: new BailoutPage(page),
capabilityQuestionsPage: new CapabilityQuestionsPage(page),
contactConfirmationPage: new ContactConfirmationPage(page),
@ -206,8 +209,7 @@ export default class TestCase extends DisposableBase implements ITestCase {
vehicleLookupAddressPage: new VehicleLookupAddressPage(page),
vehicleLookupLicensePage: new VehicleLookupLicensePage(page),
welcomePage: new WelcomePage(page),
moldingQuestionsPage: new MoldingQuestionsPage(page),
addressLookupPage: new AddressLookupPage(page)
moldingQuestionsPage: new MoldingQuestionsPage(page)
};
}

View file

@ -0,0 +1,21 @@
import { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { IAddressVehicleDetails } from '@business-logic/types/CustomerDetails';
export class AddressVehiclesPage extends BasePage {
readonly page: Page;
readonly selectVehicleButton: Locator;
issPageValue = 'address-vehicles';
constructor(page: Page) {
super(page);
this.page = page;
this.selectVehicleButton = this.page.getByRole('radio').first();
}
async selectVehicle(addressVehicleDetails: IAddressVehicleDetails){
const vehicleRegExp = new RegExp(`${addressVehicleDetails.year} .+ ${addressVehicleDetails.model}`, 'i');
await this.page.locator('label').filter({hasText: vehicleRegExp}).locator('div').click();
}
}

View file

@ -18,8 +18,6 @@ export class BailoutPage extends BasePage {
this.lastNameTextBox = this.page.locator('#lastNameField');
this.phoneNumberTextBox = this.page.locator('#phoneNumberField');
this.emailAddressTextBox = this.page.locator('#emailAddressField');
// this.page.waitForLoadState();
// this.validateURL(this.url);
}
async validateBailoutDetails(customerDetails: ICustomerDetails, bailoutCode: number) {
@ -31,6 +29,10 @@ export class BailoutPage extends BasePage {
expect.soft(await this.getBailoutCode()).toEqual(bailoutCode);
}
async validateBailoutCode(bailoutCode: number) {
expect.soft(await this.getBailoutCode()).toEqual(bailoutCode);
}
async validateBailoutDetailsNotNull(){
await this.firstNameTextBox.waitFor({state:'visible'})
expect(this.firstNameTextBox.inputValue()).not.toBe('');

View file

@ -132,6 +132,6 @@ export class BasePage {
await expect(async () => {
const currentUrl = this.page.url();
expect(currentUrl).not.toEqual(startingUrl);
}).toPass({ timeout: 60_000 });
}).toPass({ timeout: 70_000 });
}
}

View file

@ -1,6 +1,6 @@
import test, { expect, type Locator, type Page } from '@playwright/test';
import { BasePage } from './BasePage';
import { ICustomerDetails, IVehicleDetails } from '@business-logic/types/CustomerDetails';
import { ICustomerDetails, IVehicleDetails, IAddressVehicleDetails } from '@business-logic/types/CustomerDetails';
import { PaymentType, ServicePackage } from '@business-logic/types/Enums';
import { ITestData } from '@business-logic/types/ITestData';
@ -50,8 +50,8 @@ export class OrderConfirmationPage extends BasePage {
async validateOrderConfirmationPage(testData: Partial<ITestData>) {
// Destructure data we use
const { vehicleDetails, customerDetails, servicePackage, isItac,
isNoComp, isPolicyFound, claimDetails, paymentDetails, isUseVehicleOnPolicy } = testData;
const { vehicleDetails, servicePackage, isItac,
isNoComp, isPolicyFound, claimDetails, paymentDetails, isUseVehicleFromAddressLookup, addressVehicleDetails } = testData;
// Grab text
@ -62,7 +62,7 @@ export class OrderConfirmationPage extends BasePage {
// Derived conditions
const isItacOrNoComp = !!(isItac || isNoComp);
const isUnverified = !isPolicyFound;
const isUnverified = !isPolicyFound || claimDetails!.policyDeductible === -1;
const isUnverifiedPolicyAfterVehicleLookup = testData.isUnverifiedPolicyAfterVehicleLookup === true;
const hasPremiumOrStandard =
(claimDetails!.policyDeductible >= 0 || !isPolicyFound) &&
@ -84,18 +84,20 @@ export class OrderConfirmationPage extends BasePage {
const lineItemsValue = await textIf(hasPremiumOrStandard, this.cartLineItemsText);
const deductibleTextValue = await textIf(!isItacOrNoComp, this.deductibleText);
const subtotalTextValue = await textIf((hasPremiumOrStandard || isItacOrNoComp) && !isUnverified && !isUnverifiedPolicyAfterVehicleLookup, this.subtotalText);
const totalAmountDueValue = await textIf((hasPremiumOrStandard && !payAtService) || (isItacOrNoComp && !payAtService) && !isUnverified && !isUnverifiedPolicyAfterVehicleLookup, this.totalAmountDueText);
const amountPaidTextValue = await textIf((hasPremiumOrStandard && !payAtService) || (isItacOrNoComp && !payAtService) && !isUnverified && !isUnverifiedPolicyAfterVehicleLookup, this.totalAmountDueText);
const finalAmountDueValue = await textIf(hasPremiumOrStandard || isItacOrNoComp || isUnverified || isUnverifiedPolicyAfterVehicleLookup, this.finalAmountDue);
const totalAmountDueValue = await textIf((hasPremiumOrStandard && !payAtService) && (isItacOrNoComp && !payAtService) && !isUnverified && !isUnverifiedPolicyAfterVehicleLookup, this.totalAmountDueText);
const amountPaidTextValue = await textIf((hasPremiumOrStandard && !payAtService) && (isItacOrNoComp && !payAtService) && !isUnverified && !isUnverifiedPolicyAfterVehicleLookup, this.totalAmountDueText);
const finalAmountDueValue = await textIf((hasPremiumOrStandard && isItacOrNoComp) || (hasPremiumOrStandard && isUnverified), this.finalAmountDue);
const confirmationTextValue = await this.confirmationText.textContent();
// General Validations
expect.soft(this.serviceText).toBeVisible();;
expect.soft(this.successHeader).toBeVisible();
expect.soft(confirmationTextValue).toContain('Your appointment is on Safelite\'s schedule and your confirmation email is on the way.');
expect.soft(serviceTextValue).toContain(`${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`);
if (isUseVehicleFromAddressLookup) {
expect.soft(serviceTextValue).toContain(`${addressVehicleDetails!.year} ${addressVehicleDetails!.make} ${addressVehicleDetails!.model}`);
} else {
expect.soft(serviceTextValue).toContain(`${vehicleDetails!.year} ${vehicleDetails!.make} ${vehicleDetails!.model}`);
}
// Validate order number and appointment type header
await this.validateOrderNumber();
@ -115,15 +117,24 @@ export class OrderConfirmationPage extends BasePage {
if (isPolicyFound && (claimDetails!.policyDeductible === 0 && (servicePackage === ServicePackage.GlassOnly))) {
const zeroDeductibleText = await this.deductibleText.textContent();
expect.soft(zeroDeductibleText).toEqual('$0.00');
} else if (isPolicyFound && claimDetails!.policyDeductible > 0 && !(isItac || isNoComp) && servicePackage === ServicePackage.GlassOnly){
} else if (isPolicyFound && claimDetails!.policyDeductible > 0 && !(isItac || isNoComp) && !isUnverifiedPolicyAfterVehicleLookup && servicePackage === ServicePackage.GlassOnly){
expect.soft(deductibleTextValue).not.toBeNull();
const deductibleAmt = deductibleTextValue ? Number.parseFloat(deductibleTextValue.split('$')[1].replaceAll(',', '')) : 0;
expect.soft(deductibleAmt).toEqual(claimDetails!.policyDeductible);
} else if ((isPolicyFound || isItac || (isNoComp && paymentDetails!.paymentType === PaymentType.PayAtService)) && !isUnverifiedPolicyAfterVehicleLookup && finalAmountDueValue !== null && subtotalTextValue !== null) {
} else if (isPolicyFound && claimDetails!.policyDeductible > 0 && !(isItac || isNoComp) && !isUnverifiedPolicyAfterVehicleLookup && hasPremiumOrStandard && !payAtService) {
// Policy found, deductible > 0, Standard/Premium package, paid with PIA (not pay-at-service)
expect.soft(deductibleTextValue).not.toBeNull();
const deductibleAmt = deductibleTextValue ? Number.parseFloat(deductibleTextValue.split('$')[1].replaceAll(',', '')) : 0;
expect.soft(deductibleAmt).toEqual(claimDetails!.policyDeductible);
const totalAmountDueAmt = totalAmountDueValue ? Number.parseFloat(totalAmountDueValue!.split('$')[1].replaceAll(',', '')) : null;
const amountPaidValue = amountPaidTextValue ? Number.parseFloat(amountPaidTextValue!.split('$')[1].replaceAll(',', '')) : null;
expect.soft(amountPaidValue).toEqual(totalAmountDueAmt);
} else if ((isPolicyFound && isItac && (isNoComp && paymentDetails!.paymentType === PaymentType.PayAtService)) && !isUnverifiedPolicyAfterVehicleLookup && finalAmountDueValue !== null && subtotalTextValue !== null) {
// Extract numbers
const deductibleAmt = deductibleTextValue ? Number.parseFloat(deductibleTextValue.split('$')[1].replaceAll(',', '')) : null;
const subtotalAmt = subtotalTextValue ? Number.parseFloat(subtotalTextValue!.split('$')[1].replaceAll(',', '')) : null;
@ -146,13 +157,15 @@ export class OrderConfirmationPage extends BasePage {
expect.soft(amountPaidValue).toEqual(totalAmountDueAmt);
expect.soft(finalAmountDueAmt).toEqual(0);
}
} else if (isUnverified && servicePackage === ServicePackage.GlassOnly) {
expect.soft(deductibleTextValue).toEqual('Verifying coverage');
} else {
// essential flows will have deductible and amount due as "Verifying coverage"
const verifyingCoverageText = this.unverifiedCoverageDeductibleText;
expect.soft(verifyingCoverageText).toContainText('Verifying coverage');
if (isUnverified && servicePackage !== ServicePackage.GlassOnly) {
// essential flows will have deductible and amount due as "Verifying coverage";
expect.soft(deductibleTextValue).toEqual('Verifying coverage');
expect.soft(finalAmountDueValue).toEqual('Verifying coverage');
}
}
}
}
async validateOrderNumber() {

View file

@ -35,7 +35,7 @@ export class PaymentMethodPage extends BasePage {
this.payAtAppointmentButton = this.page.locator('[buttonlabel="Pay at my appointment"]');
this.textReminderYesButton = this.page.locator('div.button-content', { hasText: /^yes$/i });
this.textReminderNoButton = this.page.locator('div.button-content', { hasText: 'No' });
this.textReminderNoButton = this.page.locator('div.button-content', { hasText: /^no$/i });
this.continueToCheckoutButton = this.page.getByRole('button', { name: 'Continue to checkout' });
this.submitButton = this.page.getByRole('button', { name: 'Submit' });
}
@ -46,20 +46,20 @@ export class PaymentMethodPage extends BasePage {
switch (paymentDetails.paymentType) {
case PaymentType.Credit:
await this.payNowButton.click();
await this.textReminderYesButton.click();
await this.textReminderNoButton.click();
await this.continueToCheckoutButton.click();
await this.selectCreditCard(paymentDetails);
break;
case PaymentType.Paypal:
await this.payNowButton.click();
await this.textReminderYesButton.click();
await this.textReminderNoButton.click();
await this.continueToCheckoutButton.click();
await this.selectPaypal();
await this.paypalPage.completePaypalPurchase(paymentDetails);
break;
case PaymentType.AfterPay:
await this.payInFourButton.click();
await this.textReminderYesButton.click();
await this.textReminderNoButton.click();
await this.continueToCheckoutButton.click();
// Capture popup
@ -72,7 +72,7 @@ export class PaymentMethodPage extends BasePage {
case PaymentType.PayAtService:
await this.payAtAppointmentButton.click();
await this.textReminderYesButton.click();
await this.textReminderNoButton.click();
await this.submitButton.click();
break;
default:
@ -94,7 +94,7 @@ export class PaymentMethodPage extends BasePage {
}
async submitOrderWithoutPIA() {
await this.textReminderYesButton.click();
await this.textReminderNoButton.click();
await this.submitButton.click();
}
}

View file

@ -24,8 +24,14 @@ export class PaypalPage extends BasePage {
}
async completePaypalPurchase(paymentDetails: IPaymentDetails) {
await this.usernameTextBox.fill(paymentDetails.username!);
await this.nextButton.click();
await expect(async () => {
await this.usernameTextBox.fill(paymentDetails.username!);
await this.nextButton.waitFor({ state: 'visible', timeout: 5000 });
await this.nextButton.click();
await expect(this.passwordTextBox).toBeVisible({ timeout: 5000 });
}).toPass({ timeout: 30000 });
await this.passwordTextBox.fill(paymentDetails.password!);
await this.paypalLoginButton.click();
await this.payButton.click();

View file

@ -48,7 +48,7 @@ export class PolicyHolderDetailsPage extends BasePage {
await this.addressInputBox.fill(customerDetails.address.street);
// Wait for suggestions to load (Google Places has a slight delay)
await this.page.locator('.pac-item').first().waitFor({ state: 'visible', timeout: 5000 });
await this.page.locator('.pac-item').first().waitFor({ state: 'visible', timeout: 6000 });
// Click the first result
await this.page.locator('.pac-item').first().click();

View file

@ -40,17 +40,11 @@ export class ProviderPreferencePage extends BasePage {
this.stateLawModalOkayButton = this.page.getByRole('button', { name: 'Okay' })
}
async selectProvider(isSafelite = true) {
async selectProvider(isSafelite: boolean) {
if (isSafelite) {
await this.scheduleNowButton.click();
await this.nextPage();
}
else {
await this.findAnotherShopButton.waitFor({ state: 'visible' });
await this.findAnotherShopButton.click();
await this.tpaRecalModal.waitFor({ state: 'visible' });
await this.scheduleTPAWithAdas();
}
}
async scheduleWithSafeliteADAS() {
@ -60,8 +54,11 @@ export class ProviderPreferencePage extends BasePage {
}
async scheduleTPAWithAdas() {
await this.findAnotherShopButton.waitFor({ state: 'visible' });
await this.findAnotherShopButton.click();
await this.tpaRecalModal.waitFor({ state: 'visible' });
await this.learnMoreLink.click();
await this.noButton.click();
await this.noButton.click(); // continue to schedule with TPA even with recal disclaimer
await this.acknowledgeAdasCheckbox.click();
await this.tpaRecalModalContinueButton.click();
}

View file

@ -9,7 +9,7 @@ export class TpaSearchPage extends BasePage {
constructor(page: Page) {
super(page);
this.page = page;
this.firstLocationButton = page.locator('div.button-content').first();
this.firstLocationButton = page.locator('div.button-content').filter({ hasNotText: /safelite/i }).first();
}
async selectFirstLocation() {

View file

@ -21,9 +21,13 @@ export class TpaSubmitPage extends BasePage {
this.deductible = page.locator('span#deductible-value, span.deductible-value');
}
async validateDeductible(claimDetails: IClaimDetails) {
await expect(this.deductible).toContainText(claimDetails.policyDeductible.toLocaleString());
}
async validateDeductible(claimDetails: IClaimDetails, isUnverifiedPolicyAfterVehicleLookup: boolean, isPolicyFound: boolean) {
const deductibleTextValue = await this.deductible.textContent();
if (claimDetails.policyDeductible !== -1 && !isUnverifiedPolicyAfterVehicleLookup) {
expect.soft(deductibleTextValue).toContain(claimDetails.policyDeductible.toLocaleString());
} else
expect.soft(deductibleTextValue).toEqual('Verifying coverage');
}
// TODO: Validate change preferred shop and contact details flows
}

View file

@ -11,8 +11,10 @@ export default class VehiclePartQuestionsPage extends PartQuestionsPage{
async selectPartQuestionResponses(partQuestions: IPartQuestion[]) {
for (const pq of partQuestions) {
const escaped = pq.optionToSelect.replace(/"/g, '\\"');
const parentobject=this.page.locator(`fieldset[aria-labelledby="${pq.partQuestionType}"]`);
const partQuestionOptionButton = parentobject.locator(`[buttonlabel="${pq.optionToSelect}"]`);
const partQuestionOptionButton = parentobject.locator(`[buttonlabel="${escaped}"]`);
await partQuestionOptionButton.nth(0).click();
if (pq.secondaryQuestionOptionToSelect != null) {
const secondaryQuestionButton = parentobject.getByText(`${pq.secondaryQuestionOptionToSelect}`);

View file

@ -25,7 +25,6 @@ import advancedScenario0003TestCases from "./advanced/0003a_MobileAfterpay";
import essentialReplaceDynamicAdasTests from "./0005_EssentialReplaceDynamicAdas";
import essentialReplaceStaticAdasTests from "./0001_EssentialReplaceStatisAdas";
import essentialVehicleLookupBailoutTests from "./0020_EssentialVehicleLookupBailout";
import essentialPriceServiceErrorBailoutTests from "./0021_EssentialPriceServiceErrorBailout";
import essentialServiceableBigTruckTestCases from "./0022_EssentialServiceableBigTruck";
import essentialNonServiceableBigTruckTestCases from "./0023_EssentialNonServiceableBigTruck";
import essentialNonServiceableBigTruckVinTestCases from "./0024_EssentialNonServiceableBigTruckVin";
@ -54,7 +53,7 @@ import advancedScenario0021TestCases from "./advanced/0021a_VehicleByPlate";
import advancedScenario0022TestCases from "./advanced/0022a_VehicleByVIN";
import advancedScenario0023TestCases from "./advanced/0023a_VehicleByVINPartsQns";
import { createAccessibilityHtmlReport } from "@impl/utils/ReportUtils";
import advancedScenario0024TestCases from "./advanced/0024a_VehicleByVINUnverifiedBailout";
import advancedScenario0024TestCases from "./advanced/0024a_AddressVehicle";
import advancedScenario0025TestCases from "./advanced/0025a_VehicleByVINUnverifiedBailout";
import advancedScenario0026aTestCases from "./advanced/0026a_NoDeductibleAdasBailout5";
import advancedScenario0028aTestCases from "./advanced/0028a_ItacCancelMyClaim";
@ -87,7 +86,6 @@ test.describe.parallel('ISS QA Automation Regression', () => {
addSmokeTagToRandomTest(essentialTpaEnabledReplace_0018);
addSmokeTagToRandomTest(essentialTpaEnabledReplaceRecal_0019);
addSmokeTagToRandomTest(essentialVehicleLookupBailoutTests);
addSmokeTagToRandomTest(essentialPriceServiceErrorBailoutTests);
addSmokeTagToRandomTest(essentialServiceableBigTruckTestCases);
addSmokeTagToRandomTest(essentialNonServiceableBigTruckTestCases);
addSmokeTagToRandomTest(essentialNonServiceableBigTruckVinTestCases);
@ -165,11 +163,7 @@ test.describe.parallel('ISS QA Automation Regression', () => {
for (const testCase of essentialVehicleLookupBailoutTests) {
test(...prepareTest(testCase, run, options, ruleEngine)); //skipping this until SSR-2004 is fixed
}
//Scenario 21
for (const testCase of essentialPriceServiceErrorBailoutTests) {
test(...prepareTest(testCase, run, options, ruleEngine));
}
//Scenario 22
// Scenario 22
for (const testCase of essentialServiceableBigTruckTestCases) {
test(...prepareTest(testCase, run, options, ruleEngine));
}
@ -381,13 +375,13 @@ async function runWorkflow(page: Page, testCase: TestCase) {
}
// Destructure data for easy access
const { customerDetails, claimDetails, vehicleDetails, vehicleDamage,
const { customerDetails, claimDetails, vehicleDetails, addressVehicleDetails, vehicleDamage,
appointmentDetails, isSafelite, endorsements,
partQuestions, paymentDetails, isNoComp, isItac, isRecalNotification, isUnverifiedPolicyAfterVehicleLookup,
isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy,
isRecalWarning, servicePackage, hasOemEndorsement, hasStateLawPopup, otherVehiclesOnPolicy, isUseVehicleFromAddressLookup,
isSeparateApptsWarning, vehiclePartQuestions, editVehicleDetails, isAddressLookupValidations,
hasMilitaryWarning, capabilityQuestions, isUseVehicleOnPolicy,
isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin } = testCase.testData;
isVehicleLookupValidations, isMoldingQuestion, isNonServiceable, isNonServiceableVin, isRecalVehicle } = testCase.testData;
let { isPolicyFound } = testCase.testData; // Allow isPolicyFound to be re-assigned
@ -399,12 +393,12 @@ async function runWorkflow(page: Page, testCase: TestCase) {
endorsementsPage, vehicleLookupPage, partQuestionsPage, paymentMethodPage,
vehicleLookupAddressPage, vehicleLookupLicensePage, vinLookupPage,
bailoutPage, tpaSearchPage, tpaSubmitPage, tpaConfirmationPage,
vehiclePartQuestionsPage, capabilityQuestionsPage, moldingQuestionsPage, addressLookupPage } = testCase.pages;
vehiclePartQuestionsPage, capabilityQuestionsPage, moldingQuestionsPage, addressLookupPage, addressVehiclesPage } = testCase.pages;
// Destructure bailout flags
const { isVehicleSelectBailout, isTpaNotEnabledBailout,
isAPIErrorBailout, isVehicleLookupBailout, isPriceServiceErrorBailout,
isRequestCallbackBailout, isHeavyTruckVehicleBailout, isCoverageCancelledByUser } = testCase.testData.bailoutFlags || {};
isRequestCallbackBailout, isHeavyTruckVehicleBailout, isCoverageCancelledByUser, isBailoutAfterVinLookup } = testCase.testData.bailoutFlags || {};
const repairTypes: VehicleDamage[] = [
VehicleDamage.WindshieldOneChip,
@ -521,6 +515,12 @@ async function runWorkflow(page: Page, testCase: TestCase) {
await vehicleSelectionPage.nextPage();
});
if (isNonServiceable && isHeavyTruckVehicleBailout && !isBailoutAfterVinLookup) {
await bailoutPage.validateURL(bailoutPage.issPageValue);
await bailoutPage.validateBailoutCode(BailoutCode.HeavyTruckVehicle);
return;
}
await test.step('PolicyHolderDetailsPage >> Enter customer data', async () => {
await policyHolderDetailsPage.validateURL(policyHolderDetailsPage.issPageValue);
await policyHolderDetailsPage.fillCustomerDetails(customerDetails!);
@ -589,19 +589,18 @@ async function runWorkflow(page: Page, testCase: TestCase) {
if (Array.isArray(vehicleDetails?.address)) {
await addressLookupPage.validateURL(addressLookupPage.issPageValue);
await addressLookupPage.validateAddressLookupAlerts(vehicleDetails?.address!);
await addressLookupPage.nextPage();
}
});
await test.step('Address Vehicles >> Next page', async () => {
await addressLookupPage.nextPage();
await addressVehiclesPage.validateURL(addressVehiclesPage.issPageValue);
await addressVehiclesPage.selectVehicle(addressVehicleDetails!);
await addressVehiclesPage.nextPage();
});
} else {
await test.step('VehicleLookupAddressPage >> Lookup by address: ' + customerDetails!.address.street, async () => {
await vehicleLookupAddressPage.validateURL(vehicleLookupAddressPage.issPageValue);
await vehicleLookupAddressPage.lookupVehicleByAddress(customerDetails!, vehicleDetails!);
await vehicleLookupAddressPage.nextPage();
});
break;
}
break;
case VehicleLookupType.LicensePlateNumber:
@ -623,6 +622,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
await test.step('VinLookupPage >> Lookup by VIN: ' + vehicleDetails!.vin!, async () => {
await vinLookupPage.validateURL(vinLookupPage.issPageValue);
await vinLookupPage.enterVin(vehicleDetails!.vin!, isVehicleLookupValidations);
if (isNonServiceableVin) {
await vinLookupPage.handleNonServiceableVin();
return;
@ -655,13 +655,18 @@ async function runWorkflow(page: Page, testCase: TestCase) {
}
if (partQuestions && partQuestions.length > 0) {
let partQuestionsPage = testCase.pages.partQuestionsPage;
await partQuestionsPage.validateURL(partQuestionsPage.issPageValue);
await partQuestionsPage.validatePartQuestions(partQuestions);
await partQuestionsPage.selectPartQuestionResponses(partQuestions);
await partQuestionsPage.nextPage();
}
if (isHeavyTruckVehicleBailout && isBailoutAfterVinLookup) {
await bailoutPage.validateURL(bailoutPage.issPageValue);
await bailoutPage.validateBailoutCode(BailoutCode.HeavyTruckVehicle);
return;
}
if (vehiclePartQuestions && vehiclePartQuestions.length > 0) {
await vehiclePartQuestionsPage.validateURL(vehiclePartQuestionsPage.issPageValue);
await vehiclePartQuestionsPage.selectPartQuestionResponses(vehiclePartQuestions);
@ -675,8 +680,8 @@ async function runWorkflow(page: Page, testCase: TestCase) {
});
await test.step('BailoutPage >> User canceled claim on ITAC/No Comp coverage statement', async () => {
await bailoutPage.validateURL(bailoutPage.issPageValue);
await bailoutPage.validateBailoutDetails(customerDetails!, BailoutCode.CoverageCancelledByUser);
await bailoutPage.validateBailoutDetails(customerDetails!, BailoutCode.CoverageCancelledByUser);
await bailoutPage.validateURL(bailoutPage.issPageValue);
});
return;
}
@ -687,8 +692,13 @@ async function runWorkflow(page: Page, testCase: TestCase) {
if (hasOemEndorsement) {
await coverageStatementPage.validateOEMBullet();
}
if (isUseVehicleFromAddressLookup) {
await coverageStatementPage.handleUnverifiedPolicyAfterVehicleLookupFlow();
}
// For essential/unverified flows
if (!isPolicyFound) {
if (!isPolicyFound && !isUseVehicleFromAddressLookup) {
await coverageStatementPage.handleUnverifiedFlow(claimDetails!);
}
@ -719,26 +729,60 @@ async function runWorkflow(page: Page, testCase: TestCase) {
});
// If No-Comp or ITAC, ProviderPreferencePage does not appear
if (!isNoComp && !isItac) {
if (hasStateLawPopup) {
await test.step('ProviderPreferencePage >> Dismiss state law popup', async () => {
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
if (vehicleDamage!.includes(VehicleDamage.WindshieldCrack)) {
await providerPreferencePage.stateLawModalOkayButton.click();
} else {
await providerPreferencePage.stateLawModalOkayButton.click();
}
});
}
if (!isPolicyFound || !(isItac || isNoComp) && !isUnverifiedPolicyAfterVehicleLookup) {
await test.step('ProviderPreferencePage >> Select Provider ' + isSafelite ? "Safelite" : "Other shops(Non-Safelite)", async () => {
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
await providerPreferencePage.selectProvider(isSafelite);
await expect(async () => {
await providerPreferencePage.stateLawModalOkayButton.waitFor({ state: 'visible' });
await providerPreferencePage.stateLawModalOkayButton.click();
}).toPass({ timeout: 30000 });
});
}
if (isSafelite && isUnverifiedPolicyAfterVehicleLookup) {
if (isPolicyFound && isSafelite && !isUnverifiedPolicyAfterVehicleLookup) {
await test.step('ProviderPreferencePage >> Select Safelite provider', async () => {
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
await providerPreferencePage.selectProvider(isSafelite);
});
}
if (isPolicyFound && !isSafelite && isRecalVehicle) {
await test.step('ProviderPreferencePage >> Select Safelite provider', async () => {
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
await providerPreferencePage.scheduleTPAWithAdas();
});
}
if (!isPolicyFound && !(isItac || isNoComp) && !isUnverifiedPolicyAfterVehicleLookup && !isTpaNotEnabledBailout) {
if (isSafelite) {
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
await providerPreferencePage.selectProvider(isSafelite);
}
if (!isSafelite && isTpaNotEnabledBailout) {
await providerPreferencePage.scheduleTPAWithoutAdas();
await test.step('validateBailoutDetails >> Bailout code : ' + BailoutCode.TPANotEnabled, async () => {
await bailoutPage.validateURL(bailoutPage.issPageValue);
await bailoutPage.validateBailoutDetails(customerDetails!, BailoutCode.TPANotEnabled);
return;
});
return;
}
if (!isSafelite && !isTpaNotEnabledBailout) {
await providerPreferencePage.scheduleTPAWithoutAdas();
}
}
if (isSafelite && isPolicyFound && isUnverifiedPolicyAfterVehicleLookup) {
await test.step('ProviderPreferencePage >> Select Provider ' + isSafelite ? "Safelite" : "Other shops(Non-Safelite)", async () => {
await providerPreferencePage.validateURL(providerPreferencePage.issPageValue);
await providerPreferencePage.selectProvider(isSafelite);
@ -752,20 +796,13 @@ async function runWorkflow(page: Page, testCase: TestCase) {
await providerPreferencePage.scheduleTPAWithoutAdas();
});
}
// If No-Comp or ITAC, ProviderPreferencePage does not appear
}
// TPA Flow
if (!isPolicyFound || !(isItac || isNoComp) || isUnverifiedPolicyAfterVehicleLookup) {
if (!isSafelite) {
if (testCase.testData!.clientTag == '05CC1609-3631-4044-B45A-E78E13343B9A') { // Avoiding TPA flow for Federated Insureance due to Defect# SSR-1984 //Temporary fix until Defect# SSR-1984 is addressed.
await test.step('***** Performing Safelite flow for Federal Insurance due to defec# SSR-1984 *****', async () => { });
await test.step('TpaSearchPage >> TPA Search', async () => {
await tpaSearchPage.validateURL(tpaSearchPage.issPageValue);
await tpaSearchPage.selectFirstLocation();
// await tpaSearchPage.nextPage();
});
return;
}
if (isTpaNotEnabledBailout) {
await test.step('validateBailoutDetails >> Bailout code : ' + BailoutCode.TPANotEnabled, async () => {
await bailoutPage.validateURL(bailoutPage.issPageValue);
@ -775,6 +812,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
return;
}
if (!isSafelite && !isTpaNotEnabledBailout) {
await test.step('TpaSearchPage >> TPA Search', async () => {
await tpaSearchPage.validateURL(tpaSearchPage.issPageValue);
await tpaSearchPage.selectFirstLocation();
@ -783,11 +821,8 @@ async function runWorkflow(page: Page, testCase: TestCase) {
await test.step('TpaSubmitPage >> TPA Submit', async () => {
await tpaSubmitPage.validateURL(tpaSubmitPage.issPageValue);
if (!isUnverifiedPolicyAfterVehicleLookup) {
await tpaSubmitPage.validateDeductible(claimDetails!);
} else {
await tpaSubmitPage.validateDeductible(claimDetails!, isUnverifiedPolicyAfterVehicleLookup!, isPolicyFound!);
await tpaSubmitPage.nextPage();
}
});
await test.step('TpaConfirmationPage >> TPA Confirmation', async () => {
@ -797,6 +832,7 @@ async function runWorkflow(page: Page, testCase: TestCase) {
});
return;
}}
}
await test.step('SchedulePage >> Select day and time', async () => {
await schedulePage.validateURL(schedulePage.issPageValue);

View file

@ -61,7 +61,7 @@ for (const client of essentialClients) {
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
const tc = new TestCase({
name: `0002 Essential Repair Mobile Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`],
tags: [`@${client.clientTag}`, `@${client.accountName}`,'@Essentials'],
testData: data
}, undefined, '0002');
essentialRepairInShopAcuraTests.push(tc);

View file

@ -23,10 +23,10 @@ const essentialReplaceDynamicAdasData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
city: 'Chicago',
state: 'Illinois',
postalCode: '60645',
street: '9039 4th Avenue South',
city: 'Seattle',
state: 'WASHINGTON',
postalCode: '98108',
country: 'United States'
}
},
@ -50,10 +50,10 @@ const essentialReplaceDynamicAdasData: Partial<ITestData> = {
appointmentDetails: {
serviceLocation: ServiceLocation.Mobile,
serviceAddress: {
street: "2088 Haviland Road, Columbus, OH, USA",
city:"Vermillion",
state: "Ohio",
postalCode: "44089",
street: "9039 4th Avenue South",
city:"Seattle",
state: "WASHINGTON",
postalCode: "98108",
country: "undefined"
},
appointmentDate: nextWeekday
@ -69,7 +69,7 @@ for (const client of essentialClients) {
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
const tc = new TestCase({
name: `0005 Essential Replace Dynamic ADAS Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`],
tags: [`@${client.clientTag}`, `@${client.accountName}`,'@Essentials'],
testData: data
}, undefined, '0005');
essentialReplaceDynamicAdasTests.push(tc);

View file

@ -23,9 +23,9 @@ const essentialRepairMobileHyundaiData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '9220 Pennythorne Court',
city: 'Raleigh',
state: 'North Carolina',
state: 'NORTH CAROLINA',
postalCode: '27615',
country: 'United States'
}
@ -49,7 +49,7 @@ const essentialRepairMobileHyundaiData: Partial<ITestData> = {
appointmentDetails: {
serviceLocation: ServiceLocation.Mobile,
serviceAddress: {
street: "2088 Haviland Road, Columbus, OH, USA",
street: "2088 Haviland Road",
city:"Vermillion",
state: "Ohio",
postalCode: "44089",
@ -68,7 +68,7 @@ for (const client of essentialClients) {
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
const tc = new TestCase({
name: `0007 Essential Repair Hyundai Mobile Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`],
tags: [`@${client.clientTag}`, `@${client.accountName}`,'@Essentials'],
testData: data
}, undefined, '0007');
essentialRepairMobileHyundaiTests.push(tc);

View file

@ -28,7 +28,7 @@ const essentialPartsServiceErrorData: Partial<ITestData> = {
address: {
street: faker.location.streetAddress(),
city: 'Tulare',
state: 'California',
state: 'CALIFORNIA',
postalCode: '93247',
country: 'United States'
}

View file

@ -26,9 +26,9 @@ const essentialVehicleNotFoundData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '71529 Maple Street',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}
@ -74,7 +74,7 @@ for (const client of essentialClients) {
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
const tc = new TestCase({
name: `0010 Essential Vehicle Not Found Bailout Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Bailout', '@VehicleNotFound'],
tags: [`@${client.clientTag}`, `@${client.accountName}`,'@Essentials', '@Bailout', '@VehicleNotFound'],
testData: data
}, undefined, '0001');
essentialVehicleNotFoundTestCases.push(tc);

View file

@ -25,9 +25,9 @@ const essentialDoNotSeeShopData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '9799 Heartland Court',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}

View file

@ -22,9 +22,9 @@ const essentialUnqiqueGlassData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '3202 S Mason Ave',
city: 'Tacoma',
state: 'Washington',
state: 'WASHINGTON',
postalCode: '98409',
country: 'United States'
}
@ -51,13 +51,12 @@ const essentialUnqiqueGlassData: Partial<ITestData> = {
{
partQuestionType: PartQuestionType.WindshieldColor,
isOnPage: true,
optionToSelect: 'Green Tint'
optionToSelect: 'Third Visor Frit'
},
{
partQuestionType: PartQuestionType.DriverSideColor,
isOnPage: true,
optionToSelect: 'Green Tint',
secondaryQuestionOptionToSelect: 'solar, driver side, rear'
optionToSelect: 'Solar, Driver side, Rear, Movable, Exc. 118" Wb, Aftermarket'
},
],
appointmentDetails: {
@ -75,7 +74,7 @@ for (const client of essentialClients) {
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
const tc = new TestCase({
name: `0012 Essential Unique Glass Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`],
tags: [`@${client.clientTag}`, `@${client.accountName}`,'@Essentials'],
testData: data
}, undefined, '0012');
essentialUniqueGlassTests.push(tc);

View file

@ -13,46 +13,20 @@ const essentialReplaceData: Partial<ITestData> = {
isPolicyFound: false,
endorsements: [],
isReplace: false,
vehiclePartQuestions: [
{
partQuestionType: PartQuestionType.WindshieldColor,
isOnPage: true,
optionToSelect: 'Green Tint'
},
{
partQuestionType: PartQuestionType.DriverFrontColor,
isOnPage: true,
optionToSelect: 'Green Tint'
},
{
partQuestionType: PartQuestionType.DriverRearColor,
isOnPage: true,
optionToSelect: 'Green Tint'
},
{
partQuestionType: PartQuestionType.PassengerFrontColor,
isOnPage: true,
optionToSelect: 'Green Tint'
},
{
partQuestionType: PartQuestionType.PassengerRearColor,
isOnPage: true,
optionToSelect: 'Green Tint'
},
],
partQuestions: [],
isSafelite: true,
servicePackage: faker.helpers.enumValue(ServicePackage),
customerDetails: {
firstName: faker.person.firstName(),
lastName: 'Reed',
lastName: 'Tyler',
email: "itqatest@safelite.com",
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: '10212 JEWEL CT',// DO NOT use fake address here as this scenario search vehicle by address //faker.location.streetAddress(),
city: 'CONROE',
state: 'Texas',
postalCode: '77385',
street: '503 OLD CHATTANOOGA PIKE SW CLEVELAND',// DO NOT use fake address here as this scenario search vehicle by address //faker.location.streetAddress(),
city: 'Cleveland',
state: 'TENNESSEE',
postalCode: '37311',
country: 'United States'
}
},
@ -63,12 +37,12 @@ const essentialReplaceData: Partial<ITestData> = {
damageCause: DamageType.Other
},
vehicleDetails: {
year: '2015',
make: 'Ford',
model: 'F Series F150',
style: '2 door super cab',
vin: '5N1AN0NW9BC524974',
vehicleLookupType: VehicleLookupType.Address,
year: '2010',
make: 'Lincoln',
model: 'MKZ',
style: '4 door sedan',
vin: '3LNHL2JC4AR755180',
vehicleLookupType: VehicleLookupType.Vin,
},
vehicleDamage: [
VehicleDamage.WindshieldCrack,

View file

@ -23,9 +23,9 @@ const essentialRepairMobileData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
city: 'Dublin',
state: 'Ohio',
street: '123 Test Road',
city: 'Columbus',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}

View file

@ -17,7 +17,7 @@ const essentialReplaceData: Partial<ITestData> = {
{
partQuestionType: PartQuestionType.WindshieldColor,
isOnPage: true,
optionToSelect: 'Green Tint, Blue Shade'
optionToSelect: 'Solar'
},
// {
// partQuestionType: PartQuestionType.DriverFrontColor,
@ -35,10 +35,9 @@ const essentialReplaceData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
// street: faker.location.streetAddress(),
street: '456 Columbus Pike',
city: 'Dublin',
state: 'Ohio',
street: '1000 Hart Road',
city: 'Columbus',
state: 'OHIO',
postalCode: '43223',
country: 'United States'
}

View file

@ -23,9 +23,9 @@ const essentialHappyPathData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '9799 Heartland Court',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}

View file

@ -26,13 +26,11 @@ const essentialTpaEnabledData: Partial<ITestData> = {
lastName: faker.person.lastName(),
email: "itqatest@safelite.com",
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
// phoneNumber: faker.phone.toString(),
notes: 'Automated Test',
address: {
// street: faker.location.streetAddress(),
street: '134 Woodlands Place',
street: '3300 Refugee Rd',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43232',
country: 'United States'
}

View file

@ -30,10 +30,9 @@ const essentialTpaEnabledData: Partial<ITestData> = {
// phoneNumber: faker.phone.toString(),
notes: 'Automated Test',
address: {
// street: faker.location.streetAddress(),
street: '134 Woodlands Place',
street: '1st St',
city: 'Jacksonville Beach',
state: 'Florida',
state: 'FLORIDA',
postalCode: '32250',
country: 'United States'
}

View file

@ -26,9 +26,9 @@ const essentialVehicleLookupBailoutData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '6400 Emerald Parkway',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}

View file

@ -1,82 +0,0 @@
import ClientData from "@business-logic/data/ClientData";
import TestCase from "@business-logic/types/TestCase";
import { DamageType, ServiceLocation, ServicePackage, VehicleDamage, VehicleLookupType } from "@business-logic/types/Enums";
import { ITestData } from "@business-logic/types/ITestData"
import { faker } from "@faker-js/faker";
import { getNextWeekday } from "@impl/utils/DateUtils";
const nextWeekday = getNextWeekday();
const essentialPriceServiceErrorBailoutData: Partial<ITestData> = {
clientTag: 'ALL_ESSENTIAL',
isDuplicateClaim: false,
isPolicyFound: false,
endorsements: [],
isReplace: false,
partQuestions: undefined,
isSafelite: true,
bailoutFlags: {
isPriceServiceErrorBailout: true
},
servicePackage: faker.helpers.enumValue(ServicePackage),
customerDetails: {
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
email: "itqatest@safelite.com",
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
city: 'Dublin',
state: 'Ohio',
postalCode: '43016',
country: 'United States'
}
},
claimDetails: {
policyNumber: faker.string.alphanumeric(5),
policyDeductible: -1, // Not advanced, so we don't care about deductible.
damageDate: '2024-10-10',
damageCause: DamageType.Other
},
vehicleDetails: {
year: '2015',
make: 'Honda',
model: 'Accord',
style: '4 door sedan', // TODO: Check correctness of vehicle style
vehicleLookupType: VehicleLookupType.Vin,
vin: '1HGCR2E30FA099831'
},
vehicleDamage: [
// VehicleDamage.WindshieldThreeChips,
VehicleDamage.WindshieldCrack,
// VehicleDamage.DriverFrontDoor,
// VehicleDamage.DriverQuarterPanel,
// VehicleDamage.DriverRearDoor,
// VehicleDamage.PassengerFrontDoor,
// VehicleDamage.PassengerQuarterPanel,
// VehicleDamage.PassengerRearDoor,
// VehicleDamage.RearWindow
],
appointmentDetails: {
serviceLocation: ServiceLocation.InShop,
appointmentDate: nextWeekday
}
}
const essentialClients = ClientData.getEssentialClients();
const essentialPriceServiceErrorBailoutTests: TestCase[] = [];
for (const client of essentialClients) {
const data = {...essentialPriceServiceErrorBailoutData};
data.clientTag = client.clientTag;
data.isAuthenticationRequired = client.clientFlags.isAuthenticationEnabled ?? false
const tc = new TestCase({
name: `0021 Essential Price Service Error Bailout Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Bailout', '@PriceService', '@Essentials'],
testData: data
}, undefined, '0021');
essentialPriceServiceErrorBailoutTests.push(tc);
}
export default essentialPriceServiceErrorBailoutTests;

View file

@ -13,12 +13,14 @@ const essentialServiceableBigTruckData: Partial<ITestData> = {
isPolicyFound: false,
endorsements: [],
isReplace: true,
bailoutFlags: {
isHeavyTruckVehicleBailout: true,
},
vehiclePartQuestions: [
{
partQuestionType: PartQuestionType.WindshieldColor,
isOnPage: true,
optionToSelect: 'Green Tint',
secondaryQuestionOptionToSelect: 'one-piece, w/lane departure warning system',
optionToSelect: 'One-Piece, With Lane Departure Warning System',
},
],
isSafelite: true,
@ -30,9 +32,9 @@ const essentialServiceableBigTruckData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9]{3}-[0-9]{4}/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '9799 Heartland Court',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}

View file

@ -11,6 +11,10 @@ const essentialNonServiceableBigTruckData: Partial<ITestData> = {
clientTag: 'ALL_ESSENTIAL',
isDuplicateClaim: false,
isPolicyFound: false,
isNonServiceable: true,
bailoutFlags: {
isHeavyTruckVehicleBailout: true,
},
endorsements: [],
isReplace: true,
partQuestions: undefined,
@ -23,9 +27,9 @@ const essentialNonServiceableBigTruckData: Partial<ITestData> = {
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9]{3}-[0-9]{4}/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '9799 Heartland Court',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}
@ -50,8 +54,6 @@ const essentialNonServiceableBigTruckData: Partial<ITestData> = {
shopAddress: '6826 Sawmill Rd, Columbus, OH 43235',
appointmentDate: nextWeekday
},
isNonServiceable: true,
}
const essentialClients = ClientData.getEssentialClients();

View file

@ -13,26 +13,31 @@ const essentialNonServiceableBigTruckVinData: Partial<ITestData> = {
isPolicyFound: false,
endorsements: [],
isReplace: true,
isNonServiceable: true,
bailoutFlags: {
isHeavyTruckVehicleBailout: true,
isBailoutAfterVinLookup: true,
},
vehiclePartQuestions: [
{
partQuestionType: PartQuestionType.WindshieldColor,
isOnPage: true,
optionToSelect: 'Green Tint',
secondaryQuestionOptionToSelect: 'one-piece, w/lane departure warning system',
secondaryQuestionOptionToSelect: 'One-Piece, With Lane Departure Warning System',
},
],
isSafelite: true,
servicePackage: faker.helpers.enumValue(ServicePackage),
customerDetails: {
firstName: faker.person.firstName(),
lastName: faker.person.lastName(),
firstName: 'John',
lastName: 'Doe',
email: "itqatest@safelite.com",
phoneNumber: faker.helpers.fromRegExp(/[2-9][0-9][0-9]-[0-9]{3}-[0-9]{4}/),
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '9799 Heartland Court',
city: 'Dublin',
state: 'Ohio',
state: 'OHIO',
postalCode: '43016',
country: 'United States'
}
@ -48,7 +53,7 @@ const essentialNonServiceableBigTruckVinData: Partial<ITestData> = {
make: 'Freightliner',
model: 'Cascadia',
style: 'conventional cab',
vin: 'JALB4T177G7W00847',
vin: '2G5ZJ2TZ4S9105926',
vehicleLookupType: VehicleLookupType.Vin,
},
vehicleDamage: [
@ -59,7 +64,6 @@ const essentialNonServiceableBigTruckVinData: Partial<ITestData> = {
shopAddress: '6826 Sawmill Rd, Columbus, OH 43235',
appointmentDate: nextWeekday
},
isNonServiceableVin: true,
}
const essentialClients = ClientData.getEssentialClients();

View file

@ -70,7 +70,7 @@ for (const client of advancedClients) {
data.clientTag = client.clientTag;
const tc = new TestCase({
name: `0001a_Advanced_Replace_Deductible_Client: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Advanced'],
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Advanced', '@INSR-6847'],
testData: data
}, undefined, '0001a');
advancedScenario0001TestCases.push(tc);

View file

@ -75,7 +75,7 @@ const advancedScenario0002Data: Partial<ITestData> = {
// }
],
isSafelite: true,
servicePackage: faker.helpers.enumValue(ServicePackage),
servicePackage: ServicePackage.Premium,
customerDetails: customerDetails,
claimDetails: {
policyNumber: policyNumber,

View file

@ -55,7 +55,7 @@ const advancedScenario0003Data: Partial<ITestData> = {
policyNumber: policyNumber,
policyDeductible: 50,
damageDate: '2026-01-02',
damageCause: faker.helpers.enumValue(DamageType)
damageCause: DamageType.Rock
},
policySoap: policySoap,
vehicleDetails: {

View file

@ -13,7 +13,7 @@ const customerAddress: IAddress = {
street: faker.location.streetAddress(),
city: 'Hamden',
state: 'CONNECTICUT',
postalCode: '06517',
postalCode: '06518',
country: 'United States'
}
const customerDetails: ICustomerDetails = {
@ -33,7 +33,7 @@ const advancedScenario0008Data: Partial<ITestData> = {
isDuplicateClaim: false,
isPolicyFound: true,
isNoComp: false,
hasStateLawPopup: false,
hasStateLawPopup: true,
endorsements: undefined,
vehiclePartQuestions: [
// {

View file

@ -15,10 +15,10 @@ const customerDetails: ICustomerDetails = {
phoneNumber: '614-531-0031',
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
city: 'San Jose',
state: 'CA',
postalCode: '97230-6373',
street: '15603 NE Tillamook S',
city: 'Portland',
state: 'OREGON',
postalCode: '97230',
country: 'United States'
}
}
@ -32,7 +32,7 @@ const advancedScenario0021Data: Partial<ITestData> = {
isPolicyFound: true,
isUnverifiedPolicyAfterVehicleLookup: true,
isNoComp: false,
hasStateLawPopup: true,
hasStateLawPopup: false,
endorsements: undefined,
isUseVehicleOnPolicy: false,
isVehicleLookupValidations: true,

View file

@ -15,10 +15,10 @@ const customerDetails: ICustomerDetails = {
phoneNumber: '614-531-0031',
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '950 Rincon Circle',
city: 'San Jose',
state: 'CA',
postalCode: '97230-6373',
postalCode: '97230',
country: 'United States'
}
}
@ -36,9 +36,7 @@ const advancedScenario0022Data: Partial<ITestData> = {
endorsements: undefined,
isUseVehicleOnPolicy: false,
isVehicleLookupValidations: true,
vehiclePartQuestions: [
],
vehiclePartQuestions: [],
isSafelite: false,
servicePackage: faker.helpers.enumValue(ServicePackage),
customerDetails: customerDetails,

View file

@ -15,7 +15,7 @@ const customerDetails: ICustomerDetails = {
phoneNumber: '614-531-0031',
notes: 'Automated Test',
address: {
street: faker.location.streetAddress(),
street: '2682 Lane Road',
city: 'Columbus',
state: 'OH',
postalCode: '43220',
@ -34,8 +34,7 @@ const advancedScenario0024Data: Partial<ITestData> = {
hasStateLawPopup: false,
endorsements: undefined,
isUseVehicleOnPolicy: false,
isVehicleLookupValidations: false,
isVehicleSelectBailout: false,
isUseVehicleFromAddressLookup: true,
isAddressLookupValidations: true,
isMoldingQuestion: false,
isSafelite: true,
@ -43,7 +42,7 @@ const advancedScenario0024Data: Partial<ITestData> = {
customerDetails: customerDetails,
claimDetails: {
policyNumber: policyNumber,
policyDeductible: 0.00,
policyDeductible: -1,
damageDate: '2017-06-02',
damageCause: DamageType.Vandalism
},
@ -60,6 +59,11 @@ const advancedScenario0024Data: Partial<ITestData> = {
{ street: '6531 CANYON RANCH', city: 'Frisco', state: 'Texas', postalCode: '75036', lastName: 'TRAINOR' }
],
},
addressVehicleDetails: {
year: '2020',
make: 'Audi',
model: 'A6',
},
vehicleDamage: [
VehicleDamage.WindshieldCrack,
],
@ -78,7 +82,7 @@ for (const client of advancedClients) {
const data = { ...advancedScenario0024Data };
data.clientTag = client.clientTag;
const tc = new TestCase({
name: `0024a Advanced client Unlisted Vehicle Bailout: "${client.accountName}"`,
name: `0024a Advanced Client Address Vehicle Lookup: "${client.accountName}"`,
tags: [`@${client.clientTag}`, `@${client.accountName}`, '@Advanced', '@INSR-2057'],
testData: data
}, undefined, '0024a');

View file

@ -34,6 +34,7 @@ const advancedScenario0026aData: Partial<ITestData> = {
hasStateLawPopup: false,
isRecalNotification: true,
endorsements: undefined,
isRecalVehicle: true,
bailoutFlags: {
},
vehiclePartQuestions: [

View file

@ -17,8 +17,6 @@
"coverage/api/v1/coverage/register-claim": "0002a_Advanced_Replace_Deductible_Client/coverage/api/v1/coverage/register-claim.json",
"price/api/v1/price/order-items-with-itac-pricing": "0002a_Advanced_Replace_Deductible_Client/price/api/v1/price/order-items-with-itac-pricing.json",
"location/api/v1/location/providers/75023/Replace/100/550036/true/CR00056707/DW01571GTNNOEM": "0002a_Advanced_Replace_Deductible_Client/location/api/v1/location/providers/75023/Replace/100/550036/true/CR00056707/DW01571GTNNOEM.json",
"location/api/v1/location/alert-reasons/01813": "0002a_Advanced_Replace_Deductible_Client/location/api/v1/location/alert-reasons/01813.json",
"parts/api/v1/parts/rain-repel": "0002a_Advanced_Replace_Deductible_Client/parts/api/v1/parts/rain-repel.json",
"price/api/v1/price/combined-quote": "0002a_Advanced_Replace_Deductible_Client/price/api/v1/price/combined-quote.json"
"location/api/v1/location/alert-reasons/01813": "0002a_Advanced_Replace_Deductible_Client/location/api/v1/location/alert-reasons/01813.json"
}
}