Skip to content

Commit

Permalink
Initial 1.x commit
Browse files Browse the repository at this point in the history
  • Loading branch information
uberhacker committed Apr 23, 2017
1 parent 5f86d18 commit a1d5964
Show file tree
Hide file tree
Showing 5 changed files with 309 additions and 3 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
composer.phar
/vendor/
vendor

# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
# composer.lock

# Ignore testing directories
bats
bin
libexec
share
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License
The MIT License (MIT)

Copyright (c) 2017 Terminus Plugin Project
Copyright (c) 2016 Pantheon

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
46 changes: 46 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Terminus Wraith Plugin

Wraith - A Terminus plugin to assist with visual regression testing of Pantheon site environments.

## Usage:
```
$ terminus wraith [--sites site-name.test,site-name.prod --paths home=/,about=/about,news=/news,... --config --spider]
```

## Examples:
Use the previous configuration or prompt for the environments and pages to compare and then generate snapshots:
```
$ terminus wraith
```
Prompt for the environments and pages to compare and then generate snapshots:
```
$ terminus wraith --config
```
Use the previous configuration or prompt for new pages to compare the my-site.test and my-site.prod environments and then generate snapshots:
```
$ terminus wraith --sites=my-site.test,my-site.prod
```
Use the previous configuration or prompt for new environments to compare the /, /about and /news pages and then generate snapshots:
```
$ terminus wraith --pages=home=/,about=/about,news=/news
```
Use the previous configuration or prompt for new environments, craw for pages and then generate snapshots:
```
$ terminus wraith --spider
```

## Installation:

For installation help, see [Extend with Plugins](https://pantheon.io/docs/terminus/plugins/).

```
mkdir -p ~/.terminus/plugins
composer create-project -d ~/.terminus/plugins terminus-plugin-project/terminus-wraith-plugin:~1
```

## Configuration:

Install [Wraith](http://bbc-news.github.io/wraith/) for your [operating system](http://bbc-news.github.io/wraith/os-install.html). See [http://bbc-news.github.io/wraith/os-install.html](http://bbc-news.github.io/wraith/os-install.html).

## Help:
Run `terminus help wraith` for help.
37 changes: 37 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "terminus-plugin-project/terminus-wraith-plugin",
"description": "Wraith - A Terminus plugin to assist with visual regression testing of Pantheon site environments.",
"homepage": "https://github.com/terminus-plugin-project/terminus-wraith-plugin",
"authors": [
{
"name": "Ed Reel",
"email": "edreel@gmail.com",
"homepage": "https://github.com/uberhacker",
"role": "Developer"
}
],
"type": "terminus-plugin",
"keywords": [
"pantheon",
"terminus",
"regression",
"testing",
"wraith",
"plugin"
],
"support": {
"issues": "https://github.com/terminus-plugin-project/terminus-wraith-plugin/issues"
},
"license": "MIT",
"require": {
"php": "^5.5 || ^7.0"
},
"autoload": {
"psr-4": { "TerminusPluginProject\\TerminusWraith\\": "src" }
},
"extra": {
"terminus": {
"compatible-version": "^1"
}
}
}
217 changes: 217 additions & 0 deletions src/Commands/WraithCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
<?php

namespace TerminusPluginProject\TerminusWraith\Commands;

use Pantheon\Terminus\Commands\TerminusCommand;
use Pantheon\Terminus\Exceptions\TerminusException;
use Pantheon\Terminus\Site\SiteAwareInterface;
use Pantheon\Terminus\Site\SiteAwareTrait;
use Symfony\Component\Yaml\Yaml;

/**
* Assist with visual regression testing of Pantheon site environments.
*/
class WraithCommand extends TerminusCommand implements SiteAwareInterface
{

use SiteAwareTrait;

/**
* Visual regression testing with Wraith.
*
* @authorize
*
* @command wraith
*
* @option array $sites A comma separated list of site environments to compare in `site-name.env` format. Example: my-site.test,my-site.prod
* @option array $paths A comma separated list of name=value relative paths to compare. Example: home=/,about=/about,news=/news,etc.
* @option bool $config Enable configuration mode
* @option bool $spider Craw to detect pages
*
* @usage [--sites site-name.test,site-name.prod --paths home=/,about=/about,news=/news,... --config --spider]
* Generate snapshots to visually compare various pages of different site environments.
*/
public function wraith($options = ['sites' => [], 'paths' => [], 'config' => false, 'spider' => false]) {

$this->checkRequirements();

// Determine if capture configuration exists.
$capture_file = __DIR__ . '/configs/capture.yaml';
if (!file_exists($capture_file)) {
$options['config'] = true;
exec('wraith setup', $messages, $return_var);
if (!empty($messages)) {
foreach ($messages as $message) {
$this->io()->writeln($message);
}
}
}

// Override --config option if --no-interaction is set.
if ($options['no-interaction']) {
$options['config'] = false;
}

// Configuration requested.
if ($options['config']) {
// Extract capture data.
$capture_data = $this->getYaml($capture_file);

// Get the sites to compare.
if (empty($options['sites'])) {
$creds = array();
$site_envs = array();
$site_envs[] = $this->io()->ask('Enter the source in `site-name.env` format');
$login = $this->io()->confirm('Does this environment require a login?');
if (!$login) {
$creds[$site_envs[0]] = '';
} else {
$user = $this->io()->ask('Enter the username');
$pass = $this->io()->askHidden('Enter the password');
$creds[$site_envs[0]] = "${user}:${pass}@";
}
$site_envs[] = $this->io()->ask('Enter the target in `site-name.env` format');
$login = $this->io()->confirm('Does this environment require a login?');
if (!$login) {
$creds[$site_envs[1]] = '';
} else {
$user = $this->io()->ask('Enter the username');
$pass = $this->io()->askHidden('Enter the password');
$creds[$site_envs[1]] = "${user}:${pass}@";
}
} else {
$site_envs = explode(',', $options['sites'][0]);
}

// Get the site domains.
$domains = array();
foreach ($site_envs as $site_env) {
list(, $env) = $this->getSiteEnv($site_env);
$domain_info = $env->getDomains()->serialize();
foreach ($domain_info as $info) {
$domains[$info['environment']] = 'http://' . $creds[$site_env] . $info['domain'];
}
}
$capture_data['domains'] = $domains;

// Get the site paths.
if (!$options['spider']) {
$paths = array();
if (empty($options['paths'])) {
$path = $options['yes'] ? '' : '/';
while ($path) {
if ($name = $this->io()->ask('Enter the name for a relative path or `0` to cancel', 0)) {
if ($path = $this->io()->ask('Enter the url of the relative path or `0` to cancel', 0)) {
$paths[$name] = $path;
}
} else {
$path = 0;
}
}
// Need at least one page to compare.
if (empty($paths)) {
$paths['home'] = '/';
}
} else {
$pairs = explode(',', $options['paths'][0]);
foreach ($pairs as $pair) {
$values = explode('=', $pair);
$paths[$values[0]] = $values[1];
}
}
if (isset($capture_data['imports'])) {
unset($capture_data['imports']);
}
$capture_data['paths'] = $paths;
}

// Output the new configuration.
$this->putYaml($capture_file, $capture_data);
}

// Craw to detect pages.
if ($options['spider']) {
$capture_data = $this->getYaml($capture_file);
if (isset($capture_data['paths'])) {
unset($capture_data['paths']);
}
$capture_data['imports'] = 'spider_paths.yaml';
$this->putYaml($capture_file, $capture_data);
exec('wraith spider ' . $capture_file, $messages, $return_var);
if (!empty($messages)) {
foreach ($messages as $message) {
$this->io()->writeln($message);
}
}
}

// Generate snapshots.
exec('wraith capture ' . $capture_file, $messages, $return_var);
if (!empty($messages)) {
foreach ($messages as $message) {
$this->io()->writeln($message);
}
}

}

/**
* Platform independent check whether a command exists.
*
* @param string $command Command to check
* @return bool True if exists, false otherwise
*/
protected function commandExists($command)
{
$windows = (php_uname('s') == 'Windows NT');
$test_command = $windows ? 'where' : 'command -v';
$file = popen("$test_command $command", 'r');
$result = fgets($file, 255);
return $windows ? !preg_match('#Could not find files#', $result) : !empty($result);
}

/**
* Check for plugin requirements.
*/
protected function checkRequirements()
{
if (!$this->commandExists('wraith')) {
$message = 'Please install Wraith to enable visual regression testing. See http://bbc-news.github.io/wraith/os-install.html.';
throw new TerminusNotFoundException($message);
}
}

/**
* Extract YAML data.
*
* @param string $yaml_file The YAML file
* @return array An array of YAML compatible data
*/
protected function getYaml($yaml_file)
{
if ($yaml_data = @file_get_contents($yaml_file)) {
return Yaml::parse($yaml_data);
}
return array();
}

/**
* Save YAML data.
*
* @param string $yaml_file The YAML file
* @param array $yaml_data An array of YAML compatible data
*/
protected function putYaml($yaml_file, $yaml_data)
{
if (!$yaml_formatted_data = Yaml::dump($yaml_data)) {
throw new TerminusNotFoundException('Unable to save configuration. Invalid YAML data.');
}
try {
$handle = fopen($yaml_file, 'w');
fwrite($handle, $yaml_formatted_data);
fclose($handle);
} catch (Exception $e) {
throw new TerminusNotFoundException($e->getMessage());
}
}
}

0 comments on commit a1d5964

Please sign in to comment.