refactor(tests): integration tests as part of the Mocha suite

Some benefits:
- no need to check-in a full website to compare against
- targeted asserts, instead of a “should be 100% the same”
- more robust against cosmetic theme changes
- allows for testing more edge cases in the future
- can’t forget to run the integration tests since they’re part of “npm test”
pull/118/head
Romain 6 years ago
parent 7dd714c957
commit 832673f322

@ -1,22 +1,19 @@
Please make sure the tests are passing when submitting a code change.
## Automated tests
Thumbsup is covered by several types of tests.
| Command | Tests |
|---------|-------|
| npm run lint | Static code analysis |
| npm run unit | Unit tests |
| npm test | Linting + unit tests |
| scripts/record | Creates a new snapshot |
| scripts/verify | Compares a brand new gallery against the snapshot |
| scripts/cibuild | Runs all possible tests |
- static code analysis, checking for common errors and enforcing style
- unit and integration tests, with close to 100% coverage
Please make sure the tests are passing when submitting a code change.
Simply run:
Due to the nature of `thumbsup`, even some unit tests require a working runtime environment including `exiftool`, `graphicsmagick` and `ffmpeg`.
```bash
npm test
```
You can run the entire test suite inside Docker using:
Note: due to the nature of `thumbsup`, some tests require a working runtime environment including `exiftool`, `graphicsmagick` and `ffmpeg`. You can run the entire test suite inside Docker using:
```bash
docker build .
@ -25,7 +22,7 @@ docker build .
## Manual tests
For more confidence, you can also run `thumbsup` against the demo galleries at https://github.com/thumbsup/demos.
This is also valuable when working on a theme or cosmetic changes.
This is valuable when working on a theme or cosmetic changes.
```bash
# prepare local thumbsup for linking

@ -14,9 +14,6 @@ function failure {
echo "Run unit tests"
npm test
echo "Comparing gallery snapshot"
scripts/verify
echo ""
echo "=================================="
echo " ✔ Build successful"

@ -1,16 +0,0 @@
#!/bin/bash
set -eou pipefail
# Run tests inside the integration folder
DIR="${BASH_SOURCE%/*}"
pushd "${DIR}/../test-snapshot" >/dev/null || exit
trap finish EXIT
function finish {
popd >/dev/null
}
# cleanup
rm -rf output-expected
# run thumbsup
node ../bin/thumbsup.js --config config.json --output output-expected

@ -1,34 +0,0 @@
#!/bin/bash
set -eou pipefail
# Run tests inside the integration folder
DIR="${BASH_SOURCE%/*}"
pushd "${DIR}/../test-snapshot" >/dev/null || exit
trap finish EXIT
function finish {
popd >/dev/null
}
# cleanup
rm -rf output-actual
# run thumbsup
node ../bin/thumbsup.js --config config.json --output output-actual
# compare albums with the snapshot
for expected in output-expected/*.html; do
actual=$(echo "${expected}" | sed s/expected/actual/)
diff -ub "${expected}" "${actual}"
done
echo "HTML pages are identical to snapshot"
# compare media with the snapshot
IFS=$'\n'; set -f
for expected in $(find output-expected/media -name "*.jpg"); do
actual=$(echo "${expected}" | sed s/expected/actual/)
./imagediff "${expected}" "${actual}"
done
unset IFS; set +f
echo "Resized media is identical to snapshot"

@ -1,12 +0,0 @@
{
"input": "input",
"title": "Photo album",
"download-photos": "large",
"download-videos": "large",
"sort-albums-by": "title",
"sort-media-by": "date",
"albums-from": "folders",
"theme": "mosaic",
"cleanup": true,
"usage-stats": false
}

@ -1,18 +0,0 @@
#!/usr/bin/env node
const gm = require('gm')
const TOLERANCE = { tolerance: 0.005 }
const expected = process.argv[2]
const actual = process.argv[3]
gm.compare(expected, actual, TOLERANCE, (err, similar) => {
if (err) {
console.error(`Error: ${err}\n Expected: ${expected}\n Actual: ${actual}`)
process.exit(1)
}
if (!similar) {
console.error(`Images are different\n Expected: ${expected}\n Actual: ${actual}`)
process.exit(2)
}
process.exit(0)
})

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

@ -1,120 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - 2016</title>
<link rel="stylesheet" href="public/lightgallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/videojs/video-js.min.css" />
<link rel="stylesheet" href="public/core.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<div id="content">
<!--
Gallery title
-->
<header style="color: #17baef;">
<h1><a href="index.html">Photo album</a></h1>
</header>
<!--
Breadcrumbs of parent albums
-->
<nav class="breadcrumbs">
<div class="mask"></div>
<a class="breadcrumb-item" href="index.html">Home</a>
<span class="separator">&gt;</span><a class="breadcrumb-item" href="2016.html">2016</a>
</nav>
<!--
Main gallery panel
-->
<section id="content">
<!--
Nested albums, if any
-->
<ul id="albums">
</ul>
<!--
All photos and videos
-->
<ul id="media">
<li data-src="media/large/2016/2016-05-23 13.42.16.jpg"
data-sub-html=""
data-download-url="media/large/2016/2016-05-23 13.42.16.jpg">
<a href="media/large/2016/2016-05-23 13.42.16.jpg">
<img src="media/thumbs/2016/2016-05-23 13.42.16.jpg"
width="120"
height="120"
alt="2016-05-23 13.42.16.jpg" />
</a>
</li>
<li data-src="media/large/2016/2016-06-14 09.19.03.jpg"
data-sub-html=""
data-download-url="media/large/2016/2016-06-14 09.19.03.jpg">
<a href="media/large/2016/2016-06-14 09.19.03.jpg">
<img src="media/thumbs/2016/2016-06-14 09.19.03.jpg"
width="120"
height="120"
alt="2016-06-14 09.19.03.jpg" />
</a>
</li>
<li data-src="media/large/2016/2016-10-30 18.41.28.jpg"
data-sub-html=""
data-download-url="media/large/2016/2016-10-30 18.41.28.jpg">
<a href="media/large/2016/2016-10-30 18.41.28.jpg">
<img src="media/thumbs/2016/2016-10-30 18.41.28.jpg"
width="120"
height="120"
alt="2016-10-30 18.41.28.jpg" />
</a>
</li> </ul>
</section>
<!--
Optional footer
-->
</div>
<!-- Video loader -->
<div id="videos">
</div>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/videojs/video.min.js"></script>
<!-- LightGallery -->
<script src="public/lightgallery/js/lightgallery.js"></script>
<script src="public/lightgallery/js/lg-autoplay.js"></script>
<script src="public/lightgallery/js/lg-pager.js"></script>
<script src="public/lightgallery/js/lg-thumbnail.js"></script>
<script src="public/lightgallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#media").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

@ -1,116 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - 2017</title>
<link rel="stylesheet" href="public/lightgallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/videojs/video-js.min.css" />
<link rel="stylesheet" href="public/core.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<div id="content">
<!--
Gallery title
-->
<header style="color: #17baef;">
<h1><a href="index.html">Photo album</a></h1>
</header>
<!--
Breadcrumbs of parent albums
-->
<nav class="breadcrumbs">
<div class="mask"></div>
<a class="breadcrumb-item" href="index.html">Home</a>
<span class="separator">&gt;</span><a class="breadcrumb-item" href="2017.html">2017</a>
</nav>
<!--
Main gallery panel
-->
<section id="content">
<!--
Nested albums, if any
-->
<ul id="albums">
</ul>
<!--
All photos and videos
-->
<ul id="media">
<li data-src="media/large/2017/2017-01-15 12.38.41.jpg"
data-sub-html=""
data-download-url="media/large/2017/2017-01-15 12.38.41.jpg">
<a href="media/large/2017/2017-01-15 12.38.41.jpg">
<img src="media/thumbs/2017/2017-01-15 12.38.41.jpg"
width="120"
height="120"
alt="2017-01-15 12.38.41.jpg" />
</a>
</li>
<li data-html="#media5"
data-download-url="media/large/2017/2017-03-22 20.12.58.mp4">
<a href="media/large/2017/2017-03-22 20.12.58.mp4">
<img src="media/thumbs/2017/2017-03-22 20.12.58.jpg"
width="120"
height="120"
alt="2017-03-22 20.12.58.mp4" />
</a>
<img class="video-overlay" src="public/play.png" />
</li> </ul>
</section>
<!--
Optional footer
-->
</div>
<!-- Video loader -->
<div id="videos">
<div id="media5" style="display:none;">
<video class="lg-video-object lg-html5 video-js vjs-default-skin vjs-big-play-centered" poster="media/large/2017/2017-03-22 20.12.58.jpg" preload="none" controls>
<source src="media/large/2017/2017-03-22 20.12.58.mp4" type="video/mp4" />
Your browser does not support HTML5 video
</video>
</div>
</div>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/videojs/video.min.js"></script>
<!-- LightGallery -->
<script src="public/lightgallery/js/lightgallery.js"></script>
<script src="public/lightgallery/js/lg-autoplay.js"></script>
<script src="public/lightgallery/js/lg-pager.js"></script>
<script src="public/lightgallery/js/lg-thumbnail.js"></script>
<script src="public/lightgallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#media").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

@ -1,107 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Photo album - Home</title>
<link rel="stylesheet" href="public/lightgallery/css/lightgallery.css" />
<link rel="stylesheet" href="public/videojs/video-js.min.css" />
<link rel="stylesheet" href="public/core.css" />
<link rel="stylesheet" href="public/theme.css" />
</head>
<body>
<div id="content">
<!--
Gallery title
-->
<header style="color: #17baef;">
<h1><a href="index.html">Photo album</a></h1>
</header>
<!--
Breadcrumbs of parent albums
-->
<nav class="breadcrumbs">
<div class="mask"></div>
<a class="breadcrumb-item" href="index.html">Home</a>
</nav>
<!--
Main gallery panel
-->
<section id="content">
<!--
Nested albums, if any
-->
<ul id="albums">
<li>
<a href="2016.html">
<h3>2016</h3>
<div class="meta">
<time>23 May 2016 - 30 Oct 2016</time><span class="separator">,</span>
<span class="summary">3 photos</span>
</div>
<ul class="grid clearfix"><li><img src="media/thumbs/2016/2016-05-23 13.42.16.jpg" /></li><li><img src="media/thumbs/2016/2016-06-14 09.19.03.jpg" /></li><li><img src="media/thumbs/2016/2016-10-30 18.41.28.jpg" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li> </ul>
</a>
</li><li>
<a href="2017.html">
<h3>2017</h3>
<div class="meta">
<time>15 Jan 2017 - 22 Mar 2017</time><span class="separator">,</span>
<span class="summary">1 photo, 1 video</span>
</div>
<ul class="grid clearfix"><li><img src="media/thumbs/2017/2017-01-15 12.38.41.jpg" /></li><li><img src="media/thumbs/2017/2017-03-22 20.12.58.jpg" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li><li><img src="public/missing.png" /></li> </ul>
</a>
</li> </ul>
<!--
All photos and videos
-->
<ul id="media">
</ul>
</section>
<!--
Optional footer
-->
</div>
<!-- Video loader -->
<div id="videos">
</div>
<!-- jQuery -->
<script src="public/jquery.min.js"></script>
<!-- VideoJS -->
<script src="public/videojs/video.min.js"></script>
<!-- LightGallery -->
<script src="public/lightgallery/js/lightgallery.js"></script>
<script src="public/lightgallery/js/lg-autoplay.js"></script>
<script src="public/lightgallery/js/lg-pager.js"></script>
<script src="public/lightgallery/js/lg-thumbnail.js"></script>
<script src="public/lightgallery/js/lg-video.js"></script>
<script>
$(document).ready(function() {
$("#media").lightGallery({
thumbWidth: 80,
controls: true,
loop : false,
download: true,
counter: true,
videojs: true
});
});
</script>
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

@ -0,0 +1,105 @@
const debug = require('debug')
const glob = require('glob')
const path = require('path')
const should = require('should/as-function')
const fixtures = require('../fixtures')
const index = require('../../src/index')
describe('Full integration', function () {
this.slow(5000)
this.timeout(5000)
var tmpdir = null
var options = null
before(() => {
const image = fixtures.fromDisk('photo.jpg')
tmpdir = fixtures.createTempStructure({
'input/london/IMG_0001.jpg': image,
'input/london/IMG_0002.jpg': image,
'input/newyork/day 1/IMG_0003.jpg': image,
'input/newyork/day 2/IMG_0004.jpg': image
})
options = {
input: path.join(tmpdir, 'input'),
output: path.join(tmpdir, 'output'),
title: 'Photo album',
theme: 'classic',
log: 'info'
}
})
// Listr uses control.log() to print progress
// But so does Mocha to print test results
// So we override it for the duration of the integration test
beforeEach(() => {
console.logOld = console.log
console.log = debug('thumbsup:info')
debug.reset()
})
afterEach(() => {
console.log = console.logOld
})
it('builds the gallery from scratch', function (testDone) {
index.build(options, err => {
// Reset the logger ASAP to print the test status
console.log = console.logOld
// Check for any errors
should(err).eql(null)
debug.assertNotContains('thumbsup:error')
// Check the contents of the output folder
const actualFiles = actualStructure(options.output)
// Database
assertExist(actualFiles, [
'thumbsup.db'
])
// Albums
assertExist(actualFiles, [
'index.html',
'london.html',
'newyork-day1.html',
'newyork-day2.html'
])
// Thumbnails
assertExist(actualFiles, [
'media/thumbs/london/IMG_0001.jpg',
'media/thumbs/london/IMG_0002.jpg',
'media/thumbs/newyork/day 1/IMG_0003.jpg',
'media/thumbs/newyork/day 2/IMG_0004.jpg'
])
// Large versions
assertExist(actualFiles, [
'media/large/london/IMG_0001.jpg',
'media/large/london/IMG_0002.jpg',
'media/large/newyork/day 1/IMG_0003.jpg',
'media/large/newyork/day 2/IMG_0004.jpg'
])
testDone()
})
})
it('builds the gallery a second time (nothing to do)', function (testDone) {
index.build(options, err => {
// Reset the logger ASAP to print the test status
console.log = console.logOld
should(err).eql(null)
testDone()
})
})
})
function actualStructure (dir) {
return glob.sync('**/*', {
cwd: dir,
ignore: 'public',
nodir: true,
nonull: false
})
}
function assertExist (actual, expected) {
const missing = expected.filter(f => actual.indexOf(f) === -1)
should([]).eql(missing)
}
Loading…
Cancel
Save