Code Monkey home page Code Monkey logo

multi-image-mergetool's Introduction

multi-image-mergetool Build status

Resolve multiple image conflicts at the same time

This was built to resolve conflicts in full page test screenshots where auxilary content may have changed (e.g. navigation). We prefer full page screenshots over ignored content/component based screenshots as it is less brittle and catches unexpected issues.

Features:

  • Find/resolve common image changes via overlay selection
  • Support for any image configuration (e.g. same directory, same name/different directory, Gemini, specific names)

Demo:

https://twolfson.github.io/multi-image-mergetool/index.html

Screenshot:

Screenshot from tests

Getting Started

Install the module via:

# Install multi-image-mergetool globally
npm install -g multi-image-mergetool

# Run multi-image-mergetool against a Gemini test suite
multi-image-mergetool --loader gemini
# Comparing images...
# ✘ gemini/screens/root/default-small/Chrome.png
# ✘ gemini/screens/root/default-medium/Chrome.png
# ✓ gemini/screens/root/default-large/Chrome.png
# ✓ gemini/screens/root/z-default-large2/Chrome.png
# ✓ gemini/screens/root/z-default-large3/Chrome.png
# Images matched: 3 of 5
# Server is listening on http://localhost:2020/

# Browser window will automatically be opened

# Alternatively compare one-off images by their paths
multi-image-mergetool \
    --current-images path/to/current1.png path/to/current2.png \
    --ref-images path/to/ref1.png path/to/ref2.png

# Optionally define custom diff paths
multi-image-mergetool \
    --current-images path/to/current1.png path/to/current2.png \
    --ref-images path/to/ref1.png path/to/ref2.png \
    --diff-images path/to/diff1.png path/to/diff2.png

Donations

Support this project and others by twolfson via donations

Documentation

CLI

Our CLI supports the following options:

$ multi-image-mergetool --help
multi-image-mergetool [options] --current-images <current-images...> --ref-images <ref-images...>

Options:
  --current-images   Current images for comparison (required if no --loader)  [array]
  --ref-images       Locations to load/save reference images (required if no --loader)  [array]
  --diff-images      Locations to save diff images  [array]
  --loader           Loading mechanism to find images  [string] [choices: "gemini"]
  --assert           Only perform assertions (no server). If all images match, exits with 0. Otherwise, exits with 1  [boolean]
  --port, -p         Port for server to listen on  [number] [default: 2020]
  --hostname, -h     Hostname for server to listen on  [string] [default: "localhost"]
  --verbose          Enable verbose logging  [boolean]
  --no-browser-open  Prevent browser window from opening automatically  [boolean]
  --version          Show version number  [boolean]
  --help             Show help  [boolean]

Examples:
  Load from paths:
    multi-image-mergetool --current-images current1.png current2.png --ref-images ref1.png ref2.png
    multi-image-mergetool --current-images current1.png current2.png --ref-images ref1.png ref2.png --diff-images diff1.png diff2.png
  Load from `gemini` and `gemini-report` folders:
    multi-image-mergetool --loader gemini

Notes:

  • The --current-images, --ref-images, and --diff-images must be the same length and order
    • It's okay if the ref images and diff images don't exist yet, we will show prompts in the UI to handle new images

Architecture choices

We chose to use a server/browser implementation over a desktop application (e.g. Electron) for more flexibility with little development cost. It allows us to support virtualized environments (e.g. Vagrant, Docker) without asking our users to bend over backwards.

Examples

Gemini

This repository was initially inspired by gemini-gui so we want to maintain support for a similar setup. To get Gemini set up, run the following:

# Generate `gemini` and `gemini-report`
gemini-test --reporter html

# Use `multi-image-mergetool` with `gemini` folders
multi-image-mergetool --loader gemini

Notes:

This isn't efficient due to comparing images twice and waiting for all screenshots to be taken before starting comparisons. Ideally we wrap multi-image-mergetool with a better integration or add data persistence to this library (unlikely). If you write a wrapper, please submit a PR updating this documentation.

Development

Setup

To get a local copy of multi-image-mergetool set up, run the following steps:

# Clone the repository
git clone https://github.com/twolfson/multi-image-mergetool
cd multi-image-mergetool

# Install our dependencies
npm install

# Compile our latest assets
npm run build

# Start our local multi-image-mergetool
npm run start-gemini
# or bin/multi-image-mergetool

Building files

We use gulp and browserify to compile assets. These can be run once via:

npm run build

or continuously via:

npm run develop

npm run develop will additionally start a LiveReload server

Testing

We have test suites set up on Mocha and Karma. They can be run via:

npm test

To exclusively run the browser or server tests, use:

npm run test-browser # Browser tests
npm run test-server # Server tests

# Additional helpers
npm run test-karma-develop # Watches/runs Karma tests on PhantomJS and asserts screenshots

Additionally, during testing we generate screenshots. We can assert and approve they are as expected via:

npm run test-browser-mergetool-screenshots

Releasing

Our release process has a bunch of steps so we use foundry to make them reproducable. To perform a new release, run the following:

  • Update CHANGELOG.md with new release version
  • Run foundry release <version>
    • This will take care of compiling browser-dist, updating .npmignore to match .gitignore, tagging repository, updating package.json, pushing commit/tag to GitHub, and publishing to npm

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint via npm run lint and test via npm test.

Prior art

multi-image-mergetool was inspired by:

Unlicense

As of Oct 22 2016, Todd Wolfson has released this repository and its contents to the public domain.

It has been released under the UNLICENSE.

multi-image-mergetool's People

Contributors

twolfson avatar

Stargazers

Marcel S. avatar  avatar

Watchers

James Cloos avatar  avatar  avatar

multi-image-mergetool's Issues

Catch-all issue

We have a lot of development work left but the initial proof of concept is out in the wild. Here's what's left on our plate:

  • TODO: Add JSON reporter to Gemini or build out multi-image-assert
    • Definitely add an assert tool or an --no-server flag so we can exit early
  • TODO: Simplest API will be gemini-test --reporter json || multi-image-mergetool --preset gemini (loads Gemini config, finds screens based on that, (skips initial assertion), starts server + opens browser window)
    • We are settling on making this tool generic. If someone wants anything more complex than gemini-test --reporter html || multi-image-mergetool --loader gemini (e.g. a fully integrated UI like gemini-gui), then they can write it
  • TODO: Move to statically saved images instead of Gemini generated ones
  • TODO: Test out via karma and Sauce Labs/BrowserStack?
  • TODO: Move from Jade to HTML so we can have gh-pages demo Unnecessary, we can use Jade for demo page as well
  • TODO: Add gh-pages demonstration of tool (with mock server responses)
  • TODO: Clean up scripts and dependencies
  • TODO: Include performance tests in final test suite
  • TODO: Document CLI flags (--help)
  • TODO: Add --preset gemini flag support
  • TODO: Remove external dependencies (e.g. rawgit, jQuery CDN)
  • TODO: Standardize on imgSet vs imageSet
  • TODO: Reset dev via: rm -r gemini gemini-report; cp -r gemini-report-bak/* .
  • TODO: Move to Bootstrap website for our development and demo images
  • TODO: Mockups reference https://gist.github.com/twolfson/c4236abadeada82e2686c940fb23341d
    • TODO: Add a logo?
  • TODO: Testing strategy -- Karma for browser code, with plenty of isolation for things like overlay, button scenarios, handling HTTP request (fake responses via sinon or a fixed-server). Mocha for server tests -- maybe selenium for integration test but think it's overkill. Maybe use something from server tests as fixtures for browser tests so we have contract agreement on HTTP interface
    • Test CLI (or at least test it with mocked calls)
    • Test ImageSet
      • Not tested directly but covered all interfaces via CLI and server
    • Test server HTTP interface
    • Test browser UI
  • TODO: Add CLI logging on image accept/update, its result, and images remaining
  • TODO: Add fixed nav bar which allows jumping to previous/next conflict
  • TODO: Move to localized CSS as well (i.e. no rawgit)
  • TODO: Explore moving from domo to hyperscript/hyperscript-helpers
  • TODO: Enable our asserts
  • TODO: Remove test/test-files/gemini as we no longer have setup for it/use it
  • TODO: Add CSRF support
  • TODO: Get rid of 404 warnings in Karma tests by adding /base/ images instead of data-uri Repaired by moving to imgUrl for all images and ditching prefix (we were going to have similar problem as we would need a /base prefix and no encoding)
  • TODO: Add visual tests (mostly gathered in browser suite)
    • Gather screenshots
    • Generate images for current, diff, and ref (thinking 3x3 checkerboard, 1 dot center, and diff). Maybe square border and vertical line for other?
    • Integrate screenshot validation into tests (hopefully using our tool, requires moving off of commander.js as it lacks support for variadic arguments in options, i.e. --current-images [images...])
    • Explore how to integrate screenshots into CI (considering hashing as a low cost option for now, previous imgur integration was meh)
  • TODO: Make sure we test all our expected CSS (browser, index) and scripts are loaded in server page (not sure what I was thinking here...)
  • TODO: Update test-files/README.md to use multi-image-mergetool instead of one-off script (requires --diff-images support on CLI)
  • TODO: Update test-files/README.md to use multi-image-assert (currently listens and needs Ctrl+C)
  • TODO: Be sure to test --current-images/--ref-images not existing with no --loader
  • TODO: Be sure to test --loader with Gemini
  • TODO: Be sure to test imageSet#options.diffImage support properly works
  • TODO: Add new features to overlay such as custom HTML handles for dragging and resizing (corners, edges)
  • TODO: Move ImageSet in DOM to class with singleton model for quick look up by id (will need to add reset method for tests but that's fine)
  • TODO: For overlay highlighting on similar images, create a canvas with rgba and clipped area, clone 3x, and position: absolute over image
    • We prefer this over alternative of fading original image as that requires duplicating images due to preserving original updated ref (for saving) and importing original current into a canvas for fading
  • [x] TODO: Add smooth scrolling to jump to similar images We have decided against this as we can't predict if overlay found all the images the user desired =/ (e.g. found 2 when wanted 20)
  • TODO: Fix overlay being visible after image set collapse
  • TODO: Add support for missing images in ref-images (i.e. current image is new)
    • Should be achievable via an isNew property
  • TODO: Remove our TODOs and console.logs
  • TODO: Complete all skip tests
  • Add support for remaining loaders
  • Complete overlay tests
  • See test plans at bottom of one of the test files
  • Determine why overlay jumps on image set collapse (might be related to #3)
  • Verify we don't search approved images for "Find similar images"
  • Remove querySelector calls from browser directory, there shouldn't be any need with this.saveEl
  • Explore placing mutation updates inside of render with previousState, newState as parameters (should handle loading, cachebusting images (save URLs on state), image equality, results count -- should be closer to title el)
  • Add lightbox expand support a la Imgur for shrunken images/canvases
  • Overlay loses position on window width adjustment (also look at height adjustment)

Overlay overlaying adjacent image sets on similar results found

We are finding an overlay on top of image set content from another image set when we perform the following:

  1. Get 2 failing adjacent image sets
  2. Overlay second image set
  3. Overlay first image set
  4. Find similar results such that the second image set is pushed down

Expected behavior:

  • Second overlay travels with second image set

Actual behavior:

  • Second overlay stays in place and is on top of similar image results for first image set

Explore overlay actions for approving a selected region

Sometimes I am presented with a large image and don't know if I am catching everything that is different when I look over it (humans are flawed, yey). Maybe we should add support for only approving selected region as either a button or a context option when the overlay is used (e.g. pop-up to right like Google Translator add-on)

Add support for clicking outside of image bounds for overlay

Sometimes we want an overlay that covers the entirety of a row/column (e.g. a top navigation bar). Unfortunately, unless there's really mouse good precision, it's hard to get the entire region. We should add support for clicking outside of image bounds or maybe add additive selection support (probably via SVG paths but then we get a mess about unioning regions)

Add `grep` support to file patterns

Gemini has a great feature with--grep so it can isolate what it's testing. It might be inappropriate for us as we have 1:1 input files but consider adding --grep support or at least to something that integrates more tightly with Gemini

Add support for "Approve selected area"

Sometimes we want some reassurance that we didn't miss any visual changes that we're approving. It would be nice to approve a selected area like in the multi-approval setup

Improve demo accuracy

We have created a functional demo but it's not entirely accurate:

  • Partial updates are automatically fully approved, can we diff them somehow (e.g. pixelmatch)?
  • Cachebusted images are not accepted version
  • New images show broken images instead of accepted versions

Contemplate adding base images and composite states

We had a thought last night about adding base images (e.g. a screenshot on which other screenshots would have small parts laid on top of it like notifications). After some thought we aren't fully convinced it solves actual problems without introducing even more (e.g. need to handle page shifts, what about partial opacity content). Anyway, here are our half-awake notes:

For alternate UI states (e.g. auto-read), take a base screenshot then composite transparent filtered PNG on top (e.g. checking a checkbox)


This does move to series but we have less things to approve

Not sure how to do page shifts (e.g. entire diff got shifted down, composed page always has a new row element)


Maybe fork looks-same and add shift support since it's open source


For composite, keep it simple. Declare base image then only diff composite after parent is approved


Compose isn't shift tolerant but maybe we can fix that?

I think shift ??? ??? isn't due to overlay breaking


Or maybe we say composing and shifts break simple tools so no and are edge cases so don't support them

Explore using cluster for multiple cores

Comparing images is the slowest part of our application, we should explore using cluster to parallelize our process. Alternatively, image-diff would fire up separate processes which also works

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.