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
19 changes: 19 additions & 0 deletions diffy
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,25 @@ $classLoader = require $autoloaderPath;

// Customization variables
$argv = $_SERVER['argv'];

// Handle --base-url option globally before passing argv to Robo.
foreach ($argv as $i => $arg) {
if (strpos($arg, '--base-url=') === 0) {
$baseUrl = rtrim(substr($arg, strlen('--base-url=')), '/') . '/';
\Diffy\Diffy::$baseUrl = $baseUrl;
\Diffy\Diffy::$client = null;
unset($argv[$i]);
break;
} elseif ($arg === '--base-url' && isset($argv[$i + 1])) {
$baseUrl = rtrim($argv[$i + 1], '/') . '/';
\Diffy\Diffy::$baseUrl = $baseUrl;
\Diffy\Diffy::$client = null;
unset($argv[$i], $argv[$i + 1]);
break;
}
}
$argv = array_values($argv);

$appName = "DiffyCli";
$appVersion = trim(file_get_contents(__DIR__ . '/VERSION'));
$commandClasses = [
Expand Down
101 changes: 101 additions & 0 deletions src/Commands/ScreenshotCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

class ScreenshotCommand extends Tasks
{
const UPLOAD_BATCH_SIZE = 10;
/**
* Create a screenshot from environment
*
Expand Down Expand Up @@ -229,6 +230,106 @@ public function createScreenshotBaseline($projectId, $environment, array $option
return new ResultData();
}

/**
* Create a functional test snapshot from a folder of screenshots
*
* @command screenshot:create-folder
*
* @param int $projectId ID of the project
* @param string $folderPath Path to the folder containing screenshot images (PNG/JPG)
*
* @usage screenshot:create-folder 342 ./screenshots Upload screenshots from folder as a functional test snapshot.
*/
public function createFolderScreenshot($projectId, string $folderPath)
{
$apiKey = Config::getConfig()['key'];

Diffy::setApiKey($apiKey);

if (!is_dir($folderPath)) {
$this->io()->write(sprintf('Folder not found: %s', $folderPath));
throw new InvalidArgumentException();
}

$basePath = realpath($folderPath);
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($basePath, \RecursiveDirectoryIterator::SKIP_DOTS)
);

// Collect [filepath => url] sorted by relative path for deterministic ordering.
$found = [];
foreach ($iterator as $fileInfo) {
$ext = strtolower($fileInfo->getExtension());
if (!in_array($ext, ['png', 'webp'])) {
continue;
}
$filepath = $fileInfo->getPathname();
$relativePath = ltrim(substr($filepath, strlen($basePath)), DIRECTORY_SEPARATOR);
// Build URL: replace directory separators with "-", strip extension, make URL-safe.
$withoutExt = pathinfo(str_replace(DIRECTORY_SEPARATOR, '-', $relativePath), PATHINFO_FILENAME);
$urlSlug = strtolower(preg_replace('/[^a-zA-Z0-9]+/', '-', $withoutExt));
$found[$relativePath] = ['filepath' => $filepath, 'url' => '/' . $urlSlug];
}
ksort($found);
$found = array_values($found);

if (empty($found)) {
$this->io()->write(sprintf('No PNG/WebP images found in folder: %s', $folderPath));
throw new InvalidArgumentException();
}

$batches = array_chunk($found, self::UPLOAD_BATCH_SIZE);

$progressBar = $this->io()->createProgressBar(count($found));
$progressBar->setFormat(' %current%/%max% [%bar%] %percent:3s%%');
$progressBar->start();

$screenshotId = null;
foreach ($batches as $batchIndex => $batch) {
$data = [
['name' => 'snapshotName', 'contents' => basename($basePath)],
['name' => 'functionalTest', 'contents' => '1'],
];

foreach ($batch as $key => $item) {
$filepath = $item['filepath'];
$imageSize = getimagesize($filepath);
if ($imageSize === false) {
$progressBar->finish();
$this->io()->newLine();
$this->io()->write(sprintf('Could not read image dimensions for file: %s', $filepath));
throw new InvalidArgumentException();
}
$width = $imageSize[0];

$data[] = ['name' => 'breakpoints[' . $key . ']', 'contents' => (string) $width];
$data[] = ['name' => 'urls[' . $key . ']', 'contents' => $item['url']];
$data[] = [
'Content-type' => 'multipart/form-data',
'name' => 'files[' . $key . ']',
'filename' => basename($filepath),
'contents' => file_get_contents($filepath),
];
}

if ($batchIndex === 0) {
$screenshotId = Diffy::multipartRequest('POST', 'projects/' . $projectId . '/create-custom-snapshot', $data);
} else {
Diffy::multipartRequest('POST', 'snapshots/' . $screenshotId, $data);
}

$progressBar->advance(count($batch));
}

$progressBar->finish();
$this->io()->newLine();

$this->io()->write($screenshotId);

// Successful exit.
return new ResultData();
}

/**
* Sets a new baseline from a screenshot ID.
*
Expand Down