Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

microsoft-playwright-testing: Adding new API version changes #30966

Merged
merged 9 commits into from
Sep 5, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ export const API_VERSION = "2023-10-01-preview";

export class Constants {
// Config related constants
public static readonly TEST_FRAMEWORK_NAME = "Playwright";
public static readonly TEST_FRAMEWORK_RUNNERNAME = "Playwright Test Runner";
public static readonly TEST_FRAMEWORK_NAME = "PLAYWRIGHT";
public static readonly TEST_FRAMEWORK_RUNNERNAME = "PLAYWRIGHT";
public static readonly TEST_TYPE = "WebTest";
public static readonly TEST_SDK_LANGUAGE = "JavaScript/TypeScript";
public static readonly TEST_SDK_LANGUAGE = "JAVASCRIPT";
// Placeholder version
public static readonly REPORTER_PACKAGE_VERSION = "1.0.0-beta.1";
public static readonly DEFAULT_DASHBOARD_ENDPOINT = "https://playwright.microsoft.com";
Expand All @@ -75,7 +75,7 @@ export class Constants {
public static readonly GIT_REV_PARSE = "git rev-parse --is-inside-work-tree";
public static readonly GIT_COMMIT_MESSAGE_COMMAND = 'git log -1 --pretty=format:"%s"';
public static readonly ERROR_MESSAGES_MAX_LENGTH = 100;
public static readonly API_VERSION = "2024-05-20-preview";
public static readonly API_VERSION = "2024-09-01-preview";
public static readonly NON_RETRYABLE_STATUS_CODES = [400, 403, 404, 405, 409];
public static readonly SupportedRegions: string[] = [
"eastus",
Expand All @@ -93,9 +93,9 @@ export class Constants {
// API Endpoints
public static readonly testRunsEndpoint: string = "workspaces/{workspaceId}/test-runs";
public static readonly testRunsShardEndpoint: string =
"workspaces/{workspaceId}/test-runs/{testRunId}/shards/{shardId}";
"workspaces/{workspaceId}/test-runs/{testRunId}:updateShardExecutionStatus";
public static readonly storageUriEndpoint: string =
"workspaces/{workspaceId}/test-runs/{testRunId}/resulturi";
"workspaces/{workspaceId}/test-runs/{testRunId}:createArtifactsUploadBaseUri";
public static readonly testResultsEndpoint: string =
"workspaces/{workspaceId}/test-results/upload-batch";
public static readonly getTestRun: string = "getTestRun";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export class HttpService {
url: string,
data: any | null,
token: string,
contentType: string,
correlationId: string,
): Promise<PipelineResponse> {
const pipeline = createPipelineFromOptions({
Expand All @@ -35,7 +36,7 @@ export class HttpService {
url,
method,
headers: createHttpHeaders({
"Content-Type": "application/json",
"Content-Type": contentType,
Accept: "*/*",
Authorization: `Bearer ${token}`,
"x-ms-client-request-id": `${randomUUID()}`,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import { TestRunConfig } from "./testRun";

export class Shard {
id!: string;
shardId!: string;
summary!: TestRunSummary;
resultsSummary!: TestRunResultsSummary;
testRunConfig!: TestRunConfig;
workers?: number;
uploadCompleted!: boolean;
}

export class TestRunSummary {
status!: string;
status?: string;
startTime!: string;
endTime?: string;
totalTime?: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@

export class StorageUri {
uri: string;
createdAt: string;
expiresAt: string;
accessLevel: AccessLevel;
constructor(uri: string, expiresAt: string, accessLevel: AccessLevel) {
constructor(uri: string, createdAt: string, expiresAt: string, accessLevel: AccessLevel) {
this.uri = uri;
this.createdAt = createdAt;
this.expiresAt = expiresAt;
this.accessLevel = accessLevel;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

import type { TestStatus } from "@playwright/test";
import { RawTestStep } from "../common/types";

export class TestResult {
Expand All @@ -17,7 +16,7 @@ export class TestResult {
fileName!: string;
lineNumber!: number;
retry!: number;
status!: TestStatus;
status!: string;
tags!: string[];
annotations!: string[];
webTestConfig!: WebTestConfig;
Expand All @@ -28,12 +27,12 @@ export class TestResult {
export type WebTestConfig = {
jobName: string;
projectName: string;
browserName: string;
browserType: string;
os: string;
};

export type TestResultsSummary = {
status: TestStatus;
status: string;
duration: number;
startTime: string;
attachmentsMetadata: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { ShardInfo } from "./shard";

export class TestRun {
testRunId!: string;
displayName!: string;
creatorId!: string;
creatorName?: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,12 @@ class MPTReporter implements Reporter {
return values;
});
try {
await this.serviceClient.patchTestRunShardEnd(
await this.serviceClient.postTestRunShardEnd(
result,
this.shard,
this.errorMessages,
this.uploadMetadata,
this.numWorkers,
);
reporterLogger.info(`\nTest run successfully uploaded.`);

Expand Down Expand Up @@ -210,7 +211,7 @@ class MPTReporter implements Reporter {
process.stdout.write(
`\nInitializing reporting for this test run. You can view the results at: https://playwright.microsoft.com/workspaces/${this.envVariables.accountId}/runs/${this.envVariables.runId}\n`,
);
const shardResponse = await this.serviceClient.patchTestRunShardStart();
const shardResponse = await this.serviceClient.postTestRunShardStart();
this.shard = shardResponse;
// Set test report link as environment variable. If/else to check if environment variable defined or not.
if (
Expand Down Expand Up @@ -304,7 +305,7 @@ class MPTReporter implements Reporter {
!ReporterUtils.isTimeGreaterThanCurrentPlus10Minutes(this.sasUri.expiresAt)
) {
// Renew the sas uri
this.sasUri = await this.serviceClient.getStorageUri();
this.sasUri = await this.serviceClient.createStorageUri();
reporterLogger.info(
`\nFetched SAS URI with validity: ${this.sasUri.expiresAt} and access: ${this.sasUri.accessLevel}.`,
);
Expand All @@ -317,7 +318,7 @@ class MPTReporter implements Reporter {
!ReporterUtils.isTimeGreaterThanCurrentPlus10Minutes(this.sasUri.expiresAt)
) {
// Renew the sas uri
this.sasUri = await this.serviceClient.getStorageUri();
this.sasUri = await this.serviceClient.createStorageUri();
}
this.storageClient.uploadBuffer(
this.sasUri.uri,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// Licensed under the MIT License.

export enum CI_PROVIDERS {
GITHUB_ACTIONS = "GitHub Actions",
AZURE_DEVOPS = "Azure DevOps",
DEFAULT = "Default",
GITHUB = "GITHUB",
ADO = "ADO",
DEFAULT = "DEFAULT",
// Add more CI providers as needed
}

Expand All @@ -27,20 +27,20 @@ export class CIInfoProvider {

static getCIProvider(): string | null {
if (CIInfoProvider.isGitHubActions()) {
return CI_PROVIDERS.GITHUB_ACTIONS;
return CI_PROVIDERS.GITHUB;
} else if (CIInfoProvider.isAzureDevOps()) {
return CI_PROVIDERS.AZURE_DEVOPS;
return CI_PROVIDERS.ADO;
} else {
return CI_PROVIDERS.DEFAULT;
}
}

static getCIInfo(): CIInfo {
const ciProvider = CIInfoProvider.getCIProvider();
if (ciProvider === CI_PROVIDERS.GITHUB_ACTIONS) {
if (ciProvider === CI_PROVIDERS.GITHUB) {
// Logic to get GitHub Actions CIInfo
return {
provider: CI_PROVIDERS.GITHUB_ACTIONS,
provider: CI_PROVIDERS.GITHUB,
repo: process.env["GITHUB_REPOSITORY_ID"] || null,
branch: this.getGHBranchName() || null,
author: process.env["GITHUB_ACTOR"] || null,
Expand All @@ -54,10 +54,10 @@ export class CIInfoProvider {
: null,
jobId: process.env["GITHUB_JOB"] || null,
};
} else if (ciProvider === CI_PROVIDERS.AZURE_DEVOPS) {
} else if (ciProvider === CI_PROVIDERS.ADO) {
// Logic to get Azure DevOps CIInfo
return {
provider: CI_PROVIDERS.AZURE_DEVOPS,
provider: CI_PROVIDERS.ADO,
repo: process.env["BUILD_REPOSITORY_ID"] || null,
branch: process.env["BUILD_SOURCEBRANCH"] || null,
author: process.env["BUILD_REQUESTEDFOR"] || null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
TestStep,
FullConfig,
Suite,
TestStatus,
} from "@playwright/test/reporter";
import { exec } from "child_process";
import { reporterLogger } from "../common/logger";
Expand All @@ -22,7 +21,7 @@ import { Constants } from "../common/constants";
import { EnvironmentVariables } from "../common/environmentVariables";
import { DedupedStep, RawTestStep } from "../common/types";
import { TokenType } from "../model/mptTokenDetails";
import { Shard, TestResultStatus, TestRunStatus, UploadMetadata } from "../model/shard";
import { Shard, TestRunStatus, UploadMetadata } from "../model/shard";
import { TestResult as MPTTestResult, RawTestResult } from "../model/testResult";
import { TestRun, TestRunConfig } from "../model/testRun";
import { CIInfo, CI_PROVIDERS } from "./cIInfoProvider";
Expand Down Expand Up @@ -62,6 +61,7 @@ class ReporterUtils {
this.envVariables.runId = randomUUID();
}
}
testRun.testRunId = this.envVariables.runId;
testRun.displayName = ReporterUtils.isNullOrEmpty(runName) ? randomUUID() : runName;
testRun.creatorName = this.envVariables.userName;
testRun.creatorId = this.envVariables.userId!;
Expand All @@ -85,11 +85,10 @@ class ReporterUtils {
} else {
this.envVariables.shardId = "1";
}
shard.shardId = this.envVariables.shardId;
shard.summary = {
status: TestRunStatus.RUNNING,
startTime: ReporterUtils.timestampToRFC3339(this.startTime),
};
shard.testRunConfig = this.getTestRunConfig();
shard.uploadCompleted = false;
return shard;
}
Expand All @@ -100,21 +99,16 @@ class ReporterUtils {
shard: Shard,
errorMessages: string[],
attachmentMetadata: UploadMetadata,
workers: number,
): Shard {
shard.resultsSummary = {
numTotalTests: this.totalTests,
numFailedTests: this.failedTests,
numSkippedTests: this.skippedTests,
numPassedTests: this.passedTests,
numFlakyTests: this.flakyTests,
status: result.status as TestResultStatus,
};
shard.shardId = this.envVariables.shardId ?? "1";
shard.summary.totalTime = result.duration;
shard.summary.endTime = ReporterUtils.timestampToRFC3339(Date.now());
shard.summary.status = TestRunStatus.CLIENT_COMPLETE;
shard.summary.errorMessages = errorMessages;
shard.summary.uploadMetadata = attachmentMetadata;
shard.uploadCompleted = true;
shard.workers = workers;
return shard;
}

Expand Down Expand Up @@ -163,15 +157,15 @@ class ReporterUtils {
testResult.webTestConfig = {
jobName: jobName,
projectName: test.parent.project()!.name,
browserName: browserName!,
os: os.type(),
browserType: browserName!.toUpperCase(),
os: this.getOsName(),
};
testResult.annotations = this.extractTestAnnotations(test.annotations);
testResult.tags = this.extractTestTags(test);
testResult.resultsSummary = {
status: result.status,
status: result.status.toUpperCase(),
duration: result.duration,
startTime: result.startTime.toISOString(),
startTime: result.startTime.toISOString().replace(/\.\d+Z$/, "Z"),
attachmentsMetadata: this.getAttachmentStatus(result),
};
testResult.artifactsPath = result.attachments
Expand All @@ -185,7 +179,7 @@ class ReporterUtils {

public generateMarkdownSummary(testRunUrl: string): void {
try {
if (CIInfoProvider.getCIProvider() === CI_PROVIDERS.GITHUB_ACTIONS) {
if (CIInfoProvider.getCIProvider() === CI_PROVIDERS.GITHUB) {
const markdownContent = `
#### Microsoft Playwright Testing run summary

Expand Down Expand Up @@ -394,6 +388,8 @@ class ReporterUtils {
workers: this.config.workers,
pwVersion: this.config.version,
timeout: this.config.globalTimeout,
repeatEach: this.config.projects[0].repeatEach,
retries: this.config.projects[0].retries,
shards: this.config.shard ? this.config.shard : { total: 1 },
testFramework: {
name: Constants.TEST_FRAMEWORK_NAME,
Expand Down Expand Up @@ -527,17 +523,17 @@ class ReporterUtils {
return result;
}

private getTestStatus(test: TestCase, result: TestResult): TestStatus {
private getTestStatus(test: TestCase, result: TestResult): string {
if (test.expectedStatus === result.status) {
if (result.status === "skipped") {
return "skipped";
return "SKIPPED";
} else {
return "passed";
return "PASSED";
}
} else if (result.status === "interrupted") {
return "skipped";
return "SKIPPED";
} else {
return "failed";
return "FAILED";
}
}

Expand All @@ -560,7 +556,7 @@ class ReporterUtils {

private async getRunName(ciInfo: CIInfo): Promise<string> {
if (
ciInfo.provider === CI_PROVIDERS.GITHUB_ACTIONS &&
ciInfo.provider === CI_PROVIDERS.GITHUB &&
process.env["GITHUB_EVENT_NAME"] === "pull_request"
) {
const prNumber: string = `${process.env["GITHUB_REF_NAME"]?.split("/")[0]}`;
Expand Down Expand Up @@ -605,6 +601,20 @@ class ReporterUtils {
public static isNullOrEmpty(str: string | null | undefined): boolean {
return !str || str.trim() === "";
}

private getOsName(): string {
const osType = os.type();
switch (osType) {
case "Darwin":
return "MAC";
case "Linux":
return "LINUX";
case "Windows_NT":
return "WINDOWS";
default:
return "UNKNOWN";
}
}
}

export default ReporterUtils;
Loading