Skip to content

Commit

Permalink
Merge pull request #2 from lpeidro/develop
Browse files Browse the repository at this point in the history
Transform from library to composer plugin
  • Loading branch information
lpeidro authored Oct 23, 2024
2 parents e2bd06c + 951fd7c commit 15b1db2
Show file tree
Hide file tree
Showing 15 changed files with 233 additions and 94 deletions.
101 changes: 10 additions & 91 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,98 +1,17 @@
# BackstopJS Addons
A library that extends and improves the default options provided by [BackstopJS](https://github.com/garris/BackstopJS).

## Options and features
### Composer

### Scenario setup
By default, the library applies the following optimisations to the scenarios to avoid common loading issues:
- Avoid lazy CSS loading
- Remove lazy loading and force eager on all images and iframes
- Avoid asynchronous image decoding
- Force Drupal.blazy to load all images
- Pause the Slick slider autoplay
- Wait for fonts to load
- Wait for the page to load completely
- Allow setting the `cookiePath` for the cookies.json globally to apply to all scenarios. If set in the scenario configuration, it will override the global configuration.
``composer require --dev metadrop/backstopjs-addons``

### Stop animations
Allow stopping the CSS animations on the provided CSS selectors, can be set on each scenario using the `stopAnimationsSelectors` property.
You can override the default destination of the library by adding the following parameter to the extra section
of your project's composer.json file:

```json
"scenarios": [
{
"label": "Stop animations example",
"stopAnimationsSelectors": ".selector, .selector-2"
```

### Disable filters
CSS filters can be disabled on the provided CSS selectors, can be set on each scenario using the `disableFiltersSelectors` property.

```json
"scenarios": [
{
"label": "Disable filters example",
"disableFiltersSelectors": ".selector, .selector-2"
```

### Log in and navigate to a specific page
Allow users to log in and navigate to a specific page before taking a screenshot. To use this feature you need to set at least the following options
- `loginWrapperSelector` - The selector of the element that wraps the login form.
- `loginUser` - The username to login with
- `loginPass` - The password to login with

Optionally, `loginRedirectTo` can be set to navigate to a specific page after login.

```json
"scenarios": [
{
"label": "Login and navigate to a specific page",
"loginWrapperSelector": ".login-form",
"loginUser": "user",
"loginPass": "pass",
"loginRedirectTo": "/admin"
}
```

`loginUser` and `loginPass` can be set globally in the 'backstopjsAddons' settings or in the scenario configuration. If you set the login in the global configuration, you can override it in the scenario configuration.

```json
"backstopjsAddons": {
"loginUser": "global username",
"loginPass": "global pass"
}
```

The `removeSelectors` option is applied after login and navigation.

### Wait for selector after interaction
This option allows you to wait for a selector to appear after an interaction. This feature is configured within a scenario using the `waitForSelectorAfterInteraction' property, which takes a CSS selector.

```json
"scenarios": [
{
"label": "Click an wait for selector example",
"waitForSelectorAfterInteraction": ".selector"
```

### Custom user agent by viewport
Allow a user agent to be set on the viewport.

```json
"viewports": [
{
"label": "phone",
"width": 375,
"height": 667
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1"
},
```

### Hide iframe content
This option replaces the specified iframe(s) with a grey background, maintaining the size of the iframe. This feature is configured within a scenario using the `hideIframeContent' property, which takes a comma-separated list of CSS selectors.

```json
"scenarios": [
{
"label": "Hide iframe content example",
"hideIframeContent": ".iframe-container-selector, .iframe-container-selector-2"
```
"extra": {
"backstop-addons": {
"destinition": "custom/destinition"
}
```

98 changes: 98 additions & 0 deletions addons/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# BackstopJS Addons
A library that extends and improves the default options provided by [BackstopJS](https://github.com/garris/BackstopJS).

## Options and features

### Scenario setup
By default, the library applies the following optimisations to the scenarios to avoid common loading issues:
- Avoid lazy CSS loading
- Remove lazy loading and force eager on all images and iframes
- Avoid asynchronous image decoding
- Force Drupal.blazy to load all images
- Pause the Slick slider autoplay
- Wait for fonts to load
- Wait for the page to load completely
- Allow setting the `cookiePath` for the cookies.json globally to apply to all scenarios. If set in the scenario configuration, it will override the global configuration.

### Stop animations
Allow stopping the CSS animations on the provided CSS selectors, can be set on each scenario using the `stopAnimationsSelectors` property.

```json
"scenarios": [
{
"label": "Stop animations example",
"stopAnimationsSelectors": ".selector, .selector-2"
```

### Disable filters
CSS filters can be disabled on the provided CSS selectors, can be set on each scenario using the `disableFiltersSelectors` property.

```json
"scenarios": [
{
"label": "Disable filters example",
"disableFiltersSelectors": ".selector, .selector-2"
```

### Log in and navigate to a specific page
Allow users to log in and navigate to a specific page before taking a screenshot. To use this feature you need to set at least the following options
- `loginWrapperSelector` - The selector of the element that wraps the login form.
- `loginUser` - The username to login with
- `loginPass` - The password to login with

Optionally, `loginRedirectTo` can be set to navigate to a specific page after login.

```json
"scenarios": [
{
"label": "Login and navigate to a specific page",
"loginWrapperSelector": ".login-form",
"loginUser": "user",
"loginPass": "pass",
"loginRedirectTo": "/admin"
}
```

`loginUser` and `loginPass` can be set globally in the 'backstopjsAddons' settings or in the scenario configuration. If you set the login in the global configuration, you can override it in the scenario configuration.

```json
"backstopjsAddons": {
"loginUser": "global username",
"loginPass": "global pass"
}
```

The `removeSelectors` option is applied after login and navigation.

### Wait for selector after interaction
This option allows you to wait for a selector to appear after an interaction. This feature is configured within a scenario using the `waitForSelectorAfterInteraction' property, which takes a CSS selector.

```json
"scenarios": [
{
"label": "Click an wait for selector example",
"waitForSelectorAfterInteraction": ".selector"
```

### Custom user agent by viewport
Allow a user agent to be set on the viewport.

```json
"viewports": [
{
"label": "phone",
"width": 375,
"height": 667
"userAgent": "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1"
},
```

### Hide iframe content
This option replaces the specified iframe(s) with a grey background, maintaining the size of the iframe. This feature is configured within a scenario using the `hideIframeContent' property, which takes a comma-separated list of CSS selectors.

```json
"scenarios": [
{
"label": "Hide iframe content example",
"hideIframeContent": ".iframe-container-selector, .iframe-container-selector-2"
```
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
15 changes: 12 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
{
"name": "metadrop/backstopjs-addons",
"description": "Metadrop custom backstopjs scripts",
"type": "library",
"minimum-stability": "dev",
"require": {}
"type": "composer-plugin",
"require": {
"composer-plugin-api": "^2.0"
},
"autoload": {
"psr-4": {
"Metadrop\\BackstopjsAddons\\": "src/"
}
},
"extra": {
"class": "Metadrop\\BackstopjsAddons\\InstallerPlugin"
}
}
113 changes: 113 additions & 0 deletions src/InstallerPlugin.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

namespace Metadrop\BackstopjsAddons;

use Composer\Composer;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;

/**
* Composer scripts for the BackstopJS Addons during installation.
*/
class InstallerPlugin implements PluginInterface, EventSubscriberInterface {

public function activate(Composer $composer, IOInterface $io): void
{
// noop
}

public function deactivate(Composer $composer, IOInterface $io): void
{
// noop
}

public function uninstall(Composer $composer, IOInterface $io): void
{
// noop
}


public static function getSubscribedEvents()
{
return [
ScriptEvents::POST_INSTALL_CMD => 'MoveFiles',
ScriptEvents::POST_UPDATE_CMD => 'MoveFiles',
];
}

/**
* Move the BackstopJS Addons files to the tests folder.
*
* @param \Composer\Script\Event $event
* The Composer event.
*/
public function MoveFiles(Event $event) {
$composer = $event->getComposer();

// Source
$source = $composer->getConfig()->get('vendor-dir') . '/metadrop/backstopjs-addons/addons';

// Destination
$root = $composer->getConfig()->get('vendor-dir') . '/..';

$extra = $composer->getPackage()->getExtra();
$backstop_addons_extras = $extra['backstop-addons'] ?? [];
$destination = $backstop_addons_extras['destination'] ?? 'tests/backstopjs/common/libraries/backstopjs-addons';
$destination = "{$root}/{$destination}";

if (is_dir($destination)) {
self::deleteDirectoryContents($destination);
} else {
mkdir($destination, 0755, TRUE);
}

self::copyFiles($source, $destination);
}

/**
* Copy files from source to destination.
*
* @param string $source
* The source folder.
* @param string $destination
* The destination folder.
*/
private function copyFiles($source, $destination) {
$files = scandir($source);
foreach ($files as $file) {
if ($file == '.' || $file == '..') {
continue;
}
if (is_dir($source . '/' . $file)) {
mkdir($destination . '/' . $file);
self::copyFiles($source . '/' . $file, $destination . '/' . $file);
}
else {
copy($source . '/' . $file, $destination . '/' . $file);
}
}
}

/**
* Delete directory content.
*
* @param string $dir
* The destination folder.
*/
private function deleteDirectoryContents($dir) {
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
$filePath = $dir . '/' . $file;
if (is_dir($filePath)) {
self::deleteDirectoryContents($filePath);
rmdir($filePath);
} else {
unlink($filePath);
}
}
}

}

0 comments on commit 15b1db2

Please sign in to comment.