Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ All configuration options are listed in the table below:
| Qase test plan ID | `testops.plan.id` | `QASE_TESTOPS_PLAN_ID` | undefined | No | Any integer |
| Size of batch for sending test results | `testops.batch.size` | `QASE_TESTOPS_BATCH_SIZE` | `200` | No | Any integer |
| Enable defects for failed test cases | `testops.defect` | `QASE_TESTOPS_DEFECT` | `False` | No | `True`, `False` |
| Enable public report link generation after run completion | `testops.showPublicReportLink` | `QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK` | `False` | No | `True`, `False` |
| Configuration values to associate with test run | `testops.configurations.values` | `QASE_TESTOPS_CONFIGURATIONS_VALUES` | `[]` | No | Comma-separated key=value pairs |
| Create configuration groups and values if they don't exist | `testops.configurations.createIfNotExists` | `QASE_TESTOPS_CONFIGURATIONS_CREATE_IF_NOT_EXISTS` | `False` | No | `True`, `False` |
| Status filter for test results | `testops.statusFilter` | `QASE_TESTOPS_STATUS_FILTER` | `[]` | No | Comma-separated string |
Expand Down Expand Up @@ -94,6 +95,7 @@ All configuration options are listed in the table below:
}
},
"defect": false,
"showPublicReportLink": true,
"project": "<project_code>",
"batch": {
"size": 100
Expand Down Expand Up @@ -130,6 +132,7 @@ export QASE_TESTOPS_CONFIGURATIONS_CREATE_IF_NOT_EXISTS=true
export QASE_TESTOPS_STATUS_FILTER="skipped,blocked,untested"
export QASE_TESTOPS_RUN_EXTERNAL_LINK_TYPE="jiraCloud"
export QASE_TESTOPS_RUN_EXTERNAL_LINK_URL="PROJ-123"
export QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK=true
export QASE_STATUS_MAPPING="invalid=failed,skipped=passed"
```

Expand All @@ -138,6 +141,7 @@ The `QASE_TESTOPS_CONFIGURATIONS_VALUES` should be a comma-separated list of key
### How Configurations Work

Configurations in Qase TestOps work as follows:

* **name** field represents the configuration group (e.g., "browser", "environment")
* **value** field represents the configuration item within that group (e.g., "chrome", "staging")
* When `createIfNotExists` is true, the system will:
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"scripts": {
"test": "phpunit"
},
"version": "2.1.6",
"version": "2.1.7",
"config": {
"platform": {
"php": "8.0"
Expand Down
2 changes: 1 addition & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions src/Client/ApiClientV1.php
Original file line number Diff line number Diff line change
Expand Up @@ -340,4 +340,36 @@ public function runUpdateExternalIssue(string $code, string $type, array $links)
$this->logger->error('Failed to update external issue: ' . $e->getMessage());
}
}

public function enablePublicReport(string $code, int $runId): ?string
{
try {
$this->logger->debug('Enable public report for run: ' . $runId);

// Make PATCH request to enable public report
$response = $this->client->request('PATCH', $this->clientConfig->getHost() . '/run/' . $code . '/' . $runId . '/public', [
'headers' => [
'Token' => $this->config->api->getToken(),
'Content-Type' => 'application/json',
],
'json' => [
'status' => true,
],
]);

$responseData = json_decode($response->getBody()->getContents(), true);

if (isset($responseData['result']['hash'])) {
$publicUrl = $this->appUrl . '/public/report/' . $responseData['result']['hash'];
$this->logger->info('Public report link: ' . $publicUrl);
return $publicUrl;
}

$this->logger->warning('Public report hash not found in response');
return null;
} catch (Exception $e) {
$this->logger->warning('Failed to generate public report link: ' . $e->getMessage());
return null;
}
}
}
4 changes: 4 additions & 0 deletions src/Config/ConfigLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ private function loadFromJsonFile(): QaseConfig

if (isset($data['testops']['project'])) $config->testops->setProject($data['testops']['project']);
if (isset($data['testops']['defect'])) $config->testops->setDefect($data['testops']['defect']);
if (isset($data['testops']['showPublicReportLink'])) $config->testops->setShowPublicReportLink($data['testops']['showPublicReportLink']);

if (isset($data['testops']['api']['token'])) $config->testops->api->setToken($data['testops']['api']['token']);
if (isset($data['testops']['api']['host'])) $config->testops->api->setHost($data['testops']['api']['host']);
Expand Down Expand Up @@ -147,6 +148,9 @@ private function overrideWithEnvVariables(): void
case "qase_testops_defect":
$this->config->testops->setDefect($value);
break;
case "qase_testops_show_public_report_link":
$this->config->testops->setShowPublicReportLink(filter_var($value, FILTER_VALIDATE_BOOLEAN));
break;
case "qase_testops_api_token":
$this->config->testops->api->setToken($value);
break;
Expand Down
9 changes: 9 additions & 0 deletions src/Interfaces/ClientInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,13 @@ public function createConfigurationItem(string $code, int $groupId, string $titl
* @return void
*/
public function runUpdateExternalIssue(string $code, string $type, array $links): void;

/**
* Enable public report for a test run
*
* @param string $code Project code
* @param int $runId Test run ID
* @return string|null Public report link or null on failure
*/
public function enablePublicReport(string $code, int $runId): ?string;
}
1 change: 1 addition & 0 deletions src/Interfaces/LoggerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ interface LoggerInterface
public function info(string $message): void;
public function debug(string $message): void;
public function error(string $message): void;
public function warning(string $message): void;
}
5 changes: 5 additions & 0 deletions src/Loggers/Logger.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Logger implements LoggerInterface
'INFO' => "\033[32m", // Green
'DEBUG' => "\033[36m", // Blue
'ERROR' => "\033[31m", // Red
'WARNING' => "\033[33m", // Yellow
'RESET' => "\033[0m", // Reset color
];
private bool $debug;
Expand Down Expand Up @@ -64,6 +65,10 @@ public function error(string $message): void
$this->writeLog($message, 'ERROR');
}

public function warning(string $message): void
{
$this->writeLog($message, 'WARNING');
}

private function writeLog(string $message, string $level): void
{
Expand Down
11 changes: 11 additions & 0 deletions src/Models/Config/TestopsConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class TestopsConfig
{
public ?string $project = null;
public bool $defect = false;
public bool $showPublicReportLink = false;
public ApiConfig $api;
public RunConfig $run;
public PlanConfig $plan;
Expand Down Expand Up @@ -52,4 +53,14 @@ public function setStatusFilter(array $statusFilter): void
{
$this->statusFilter = $statusFilter;
}

public function isShowPublicReportLink(): bool
{
return $this->showPublicReportLink;
}

public function setShowPublicReportLink(bool $showPublicReportLink): void
{
$this->showPublicReportLink = $showPublicReportLink;
}
}
24 changes: 24 additions & 0 deletions src/Reporters/TestOpsReporter.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ public function completeRun(): void
$this->state->completeRun(
function () {
$this->client->completeTestRun($this->config->testops->getProject(), $this->runId);

// Enable public report if configured
if ($this->config->testops->isShowPublicReportLink()) {
$this->enablePublicReportForRun();
}
}
);
}
Expand Down Expand Up @@ -300,4 +305,23 @@ private function updateExternalIssue(int $runId): void
$this->logger->error('Failed to update external issue: ' . $e->getMessage());
}
}

/**
* Enable public report for the current test run
*/
private function enablePublicReportForRun(): void
{
try {
$publicUrl = $this->client->enablePublicReport(
$this->config->testops->getProject(),
$this->runId
);

// Logger already prints the link inside the client method
// No need to print again here
} catch (Exception $e) {
// Log warning through the centralized logger
$this->logger->warning('Failed to enable public report: ' . $e->getMessage());
}
}
}
182 changes: 182 additions & 0 deletions tests/PublicReportLinkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
<?php

declare(strict_types=1);

namespace Qase\PhpCommons\Tests;

use PHPUnit\Framework\TestCase;
use Qase\PhpCommons\Config\ConfigLoader;
use Qase\PhpCommons\Loggers\Logger;

class PublicReportLinkTest extends TestCase
{
private Logger $logger;

protected function setUp(): void
{
$this->logger = new Logger();
}

public function testShowPublicReportLinkFromEnvTrue(): void
{
// Set environment variable
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK=true');

$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

$this->assertTrue($config->testops->isShowPublicReportLink());

// Clean up
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK');
}

public function testShowPublicReportLinkFromEnvFalse(): void
{
// Set environment variable
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK=false');

$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

$this->assertFalse($config->testops->isShowPublicReportLink());

// Clean up
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK');
}

public function testShowPublicReportLinkFromEnv1(): void
{
// Set environment variable with numeric value
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK=1');

$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

$this->assertTrue($config->testops->isShowPublicReportLink());

// Clean up
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK');
}

public function testShowPublicReportLinkFromEnv0(): void
{
// Set environment variable with numeric value
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK=0');

$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

$this->assertFalse($config->testops->isShowPublicReportLink());

// Clean up
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK');
}

public function testShowPublicReportLinkDefaultValue(): void
{
// Don't set environment variable
$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

// Should be false by default
$this->assertFalse($config->testops->isShowPublicReportLink());
}

public function testShowPublicReportLinkFromJsonFile(): void
{
// Create a temporary config file
$configFilePath = getcwd() . '/qase.config.json';
$configData = [
'testops' => [
'showPublicReportLink' => true,
'project' => 'TEST',
'api' => [
'token' => 'test_token'
]
]
];

file_put_contents($configFilePath, json_encode($configData));

// Load config
$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

$this->assertTrue($config->testops->isShowPublicReportLink());

// Clean up
unlink($configFilePath);
}

public function testShowPublicReportLinkFromJsonFileFalse(): void
{
// Create a temporary config file
$configFilePath = getcwd() . '/qase.config.json';
$configData = [
'testops' => [
'showPublicReportLink' => false,
'project' => 'TEST',
'api' => [
'token' => 'test_token'
]
]
];

file_put_contents($configFilePath, json_encode($configData));

// Load config
$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

$this->assertFalse($config->testops->isShowPublicReportLink());

// Clean up
unlink($configFilePath);
}

public function testShowPublicReportLinkEnvOverridesFile(): void
{
// Create a temporary config file with false
$configFilePath = getcwd() . '/qase.config.json';
$configData = [
'testops' => [
'showPublicReportLink' => false,
'project' => 'TEST',
'api' => [
'token' => 'test_token'
]
]
];

file_put_contents($configFilePath, json_encode($configData));

// Set environment variable to true
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK=true');

// Load config
$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

// Environment variable should override file config
$this->assertTrue($config->testops->isShowPublicReportLink());

// Clean up
unlink($configFilePath);
putenv('QASE_TESTOPS_SHOW_PUBLIC_REPORT_LINK');
}

public function testSetShowPublicReportLink(): void
{
$configLoader = new ConfigLoader($this->logger);
$config = $configLoader->getConfig();

// Test setter
$config->testops->setShowPublicReportLink(true);
$this->assertTrue($config->testops->isShowPublicReportLink());

$config->testops->setShowPublicReportLink(false);
$this->assertFalse($config->testops->isShowPublicReportLink());
}
}