Skip to content
8 changes: 7 additions & 1 deletion test/e2e/helpers/shield/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,13 @@ export const MOCK_CLAIM_2 = {
'0x55da3eaee9bbefd762a33413b764ee2c025ff4a2cc0a49a05896ceb24c95712f',
reimbursementWalletAddress: '0x88069b650422308bf8b472beaf790189f3f28309',
description: 'I got scammed. Please help me get my money back. T_T @_@',
attachments: [],
attachments: [
{
originalname: 'test-document.pdf',
publicUrl: 'https://mock-storage-url.com/claims/test-document.pdf',
contentType: 'application/pdf',
},
],
intercomId: `intercom_${MOCK_CLAIM_ID_2}`,
status: 'created',
};
Expand Down
56 changes: 54 additions & 2 deletions test/e2e/helpers/shield/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export class ShieldMockttpService {
isActiveUser?: boolean;
subscriptionId?: string;
coverageStatus?: 'covered' | 'not_covered' | 'malicious';
claimErrorCode?: string;
},
) {
// Mock Identity Services first as shield/subscription APIs depend on it (Auth Token)
Expand Down Expand Up @@ -76,7 +77,7 @@ export class ShieldMockttpService {
await this.#handleGetClaimsConfigurations(server);
await this.#handleGetClaims(server);
await this.#handleClaimGenerateMessage(server);
await this.#handleSubmitClaim(server);
await this.#handleSubmitClaim(server, overrides);

// Ruleset Engine APIs
await this.#handleRulesetEngine(server);
Expand Down Expand Up @@ -310,8 +311,59 @@ export class ShieldMockttpService {
.thenJson(200, MOCK_CLAIM_GENERATE_MESSAGE_RESPONSE);
}

async #handleSubmitClaim(server: Mockttp) {
async #handleSubmitClaim(
server: Mockttp,
overrides?: {
claimErrorCode?: string;
},
) {
await server.forPost(CLAIMS_API.CLAIMS).thenCallback(() => {
// Return error response if error code is specified
if (overrides?.claimErrorCode) {
const errorCode = overrides.claimErrorCode;
let errorResponse: {
statusCode: number;
json: {
errorCode: string;
message: string;
};
};

if (errorCode === 'E102') {
// TRANSACTION_NOT_ELIGIBLE
errorResponse = {
statusCode: 400,
json: {
errorCode: 'E102',
message:
'This transaction is not done within MetaMask, hence it is not eligible for claims',
},
};
} else if (errorCode === 'E203') {
// DUPLICATE_CLAIM_EXISTS
errorResponse = {
statusCode: 400,
json: {
errorCode: 'E203',
message:
'A claim has already been submitted for this transaction hash.',
},
};
} else {
// Default error
errorResponse = {
statusCode: 400,
json: {
errorCode,
message: 'Claim submission failed',
},
};
}

return errorResponse;
}

// Success response
this.#newClaimSubmitted = true;
return {
statusCode: 200,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// ShieldClaimPage class for interacting with the Shield Claim form page
import * as path from 'path';
import { Driver } from '../../../../webdriver/driver';

export default class ShieldClaimPage {
Expand All @@ -14,6 +15,8 @@ export default class ShieldClaimPage {
text: accountName,
});

private readonly claimErrorToast = '[data-testid="claim-submit-toast-error"]';

private readonly claimSuccessToast = {
text: 'Claim submission received',
tag: 'p',
Expand All @@ -25,13 +28,12 @@ export default class ShieldClaimPage {
private readonly descriptionTextarea =
'[data-testid="shield-claim-description-textarea"]';

private readonly emailHelpText = '[data-testid="shield-claim-help-text"]';

private readonly emailInput = '[data-testid="shield-claim-email-input"]';

private readonly fileUploader = '[data-testid="upload-images-file-uploader"]';
private readonly fileUploaderInput = '[data-testid="file-uploader-input"]';

private readonly hereLink = 'a[href="#"]';
private readonly impactedTxHashError =
'[data-testid="shield-claim-impacted-tx-hash-error"]';

private readonly impactedTxHashInput =
'[data-testid="shield-claim-impacted-tx-hash-input"]';
Expand All @@ -44,9 +46,6 @@ export default class ShieldClaimPage {

private readonly pageContainer = '[data-testid="submit-claim-page"]';

private readonly reimbursementWalletAddressHelpText =
'[data-testid="shield-claim-reimbursement-wallet-address-help-text"]';

private readonly reimbursementWalletAddressInput =
'[data-testid="shield-claim-reimbursement-wallet-address-input"]';

Expand Down Expand Up @@ -126,6 +125,32 @@ export default class ShieldClaimPage {
await this.driver.fill(this.descriptionTextarea, description);
}

/**
* Upload a test file to the claim form
* Uses the test-document.pdf file from the test-data folder
*/
async uploadTestFile(): Promise<void> {
console.log('Uploading test file to claim form');
const testDataPath = path.resolve(
process.cwd(),
'test/e2e/test-data/test-document.pdf',
);
const inputField = await this.driver.findElement(this.fileUploaderInput);
await inputField.sendKeys(testDataPath);
}

/**
* Verify that a file has been uploaded successfully
*
* @param fileName - The name of the file to verify
*/
async verifyFileUploaded(fileName: string): Promise<void> {
console.log(`Verifying file uploaded: ${fileName}`);
await this.driver.waitForSelector({
text: fileName,
});
}

/**
* Click the submit button
*/
Expand All @@ -138,11 +163,38 @@ export default class ShieldClaimPage {
await this.driver.waitForSelector(this.claimSuccessToast);
}

/**
* Verify inline field error message is displayed
*
* @param errorMessage - The error message text to verify
*/
async verifyFieldError(errorMessage: string): Promise<void> {
console.log(`Verifying field error message: ${errorMessage}`);
await this.driver.waitForSelector({
css: this.impactedTxHashError,
text: errorMessage,
});
}

/**
* Verify error toast message is displayed
*
* @param errorMessage - The error message text to verify
*/
async verifyToastError(errorMessage: string): Promise<void> {
console.log(`Verifying toast error message: ${errorMessage}`);
await this.driver.waitForSelector({
css: this.claimErrorToast,
text: errorMessage,
});
}

async verifyClaimData(claimData: {
email: string;
reimbursementWalletAddress: string;
impactedTxHash: string;
description: string;
uploadedFileName?: string;
}): Promise<void> {
console.log('Verifying claim data is displayed correctly');

Expand Down Expand Up @@ -178,6 +230,14 @@ export default class ShieldClaimPage {
});
console.log(`Description verified: ${claimData.description}`);

// Verify uploaded file if provided
if (claimData.uploadedFileName) {
await this.driver.waitForSelector({
text: claimData.uploadedFileName,
});
console.log(`Uploaded file verified: ${claimData.uploadedFileName}`);
}

console.log('All claim data verified successfully');
}

Expand All @@ -191,6 +251,7 @@ export default class ShieldClaimPage {
* @param formData.impactedTxnHash - The impacted transaction hash
* @param formData.reimbursementWalletAddress - The reimbursement wallet address
* @param formData.description - The case description
* @param formData.uploadTestFile - Optional flag to upload and verify test file
* @param formData.files - Optional array of file paths to upload
*/
async fillForm(formData: {
Expand All @@ -200,6 +261,7 @@ export default class ShieldClaimPage {
chainId: string;
impactedTxnHash: string;
description: string;
uploadTestFile?: boolean;
files?: string[];
}): Promise<void> {
console.log('Filling entire claim form');
Expand All @@ -213,6 +275,11 @@ export default class ShieldClaimPage {
await this.fillImpactedTransactionHash(formData.impactedTxnHash);
await this.fillDescription(formData.description);

if (formData.uploadTestFile) {
await this.uploadTestFile();
await this.verifyFileUploaded('test-document.pdf');
}

console.log('Claim form filled successfully');
}

Expand Down
Binary file added test/e2e/test-data/test-document.pdf
Binary file not shown.
Loading
Loading