exiftool-contex
is a context for zoroaster
which allows to create
ExiftoolProcess
, open it, create temp jpeg and data file, and make
sure they are removed, and exiftool
is closed in the _destroy
method.
Full API description see below.
npm i --save-dev exiftool-context
This package has to be published from a Linux, and not a Mac, because it contains a filename with unicode encoding, which will be published in a different form (see below)
Just specify ExiftoolContext
as your test suite context
.
const ExiftoolContext = require('exiftool-context')
const myModuleTestSuite = {
context: ExiftoolContext,
'should have correct metadata': (ctx) => {
const ep = ctx.create()
return ep.open().then(() => {
// Context has a number of JPEG pictures with some metadata.
return ep.readMetadata(ctx.jpegFile)
})
.then((res) => {
const file = res.data[0]
return ctx.assertJpegMetadata(file)
})
},
}
module.exports = myModuleTestSuite
zoroaster example/myModuleTestSuite
example
myModuleTestSuite.js
✓ should have correct metadata
Executed 1 tests.
Fixtures are found in ./etc
directory. These functions and properties are available:
CANON/IMG_9858.JPG
CANON/IMG_9859.JPG
You need to call ctx.createTempFile
first, after which this will be set to a temp
jpeg file, into which you can write some metadata.
You need to call ctx.createDataFile
first, after which this will be set to a data
file which can be used to open exiftool with and write commands to.
Returns exiftool
.
exiftool
will print "File not found: test/fixtures/no_such_file.jpg" in case of error,
even on windows. use this function to replace slashes on your platform.
no_such_file.jpg
no_such_file2.jpg
CANON
empty
Return a fixture file with utf-encoded filename.
./etc/fixtures/Fọto.jpg
Here's some some additional info about Mac, git and unicode which can help in times of trouble.
Git and the Umlaut problem on Mac OS X
Filename that we test against is:
\u0046\u1ECD\u0074\u006F\u002E\u006A\u0070\u0067
Fọto.jpg
: F\u1ECDto.jpg (Yoruba language) (NFC)
Fọto.jpg
: Fo\u0323to.jpg - apparently another way to represent it (NFD)
Although the actual file may be in the wanted form, if there are other files in the repo (probably preceding the test one) which are in another form, git will use their format for other files (a guess but when it was the case, the test was failing).
// snippet to check filenames in unicode
const basename = path.basename(ctx.filenameWithEncoding)
const dir = path.dirname(ctx.filenameWithEncoding)
console.log('File to read: %s', ctx.filenameWithEncoding)
console.log('Filename in unicode to read: %s', ctx.toUnicode(basename))
const res = fs.readdirSync(dir)
console.log('Files in fixtures:')
res.map(n => ` ${n}: ${ctx.toUnicode(n)}`).forEach(n => console.log(n))
A function which has hard-coded metadata in it to assert against fixtures metadata.
An ExiftoolProcess
instance. it is not set at first, call ctx.create()
before accessing.
this._ep = new exiftool.ExiftoolProcess() // use dist-exiftool binary
this._ep = new exiftool.ExiftoolProcess(bin) // use specific binary
return this // allow chaining
Create a new instance with a given bin, and assign it to self.
if (this.ep) {
return this.ep.open(options)
}
throw new Error('ep has not been created')
Open exiftool
.
this.create(bin).open(options)
Create an instance and open it.
this.ep.close()
Close instance
ep.readMetadata()
Read metadata of a file
ep.writeMetadata()
Write metadata to a file
ep.open.readMetadata()
Open ExiftoolProcess and read metadata
ep.open.writeMetadata()
Open ExiftoolProcess and write metadata
Create a new temp file for testing. Currently clones a jpeg fixture.
Create a data file which can be used to open exiftool
Write some data to the data file.
Perform the following:
- unlinkTempFile(this.dataFile)
- unlinkTempFile(this.tempFile)
That is, make sure that tests do not have open processes after them, or temp files.
Convert a string to unicode (author).
// http://buildingonmud.blogspot.ru/2009/06/convert-string-to-unicode-in-javascript.html
function toUnicode(theString) {
let unicodeString = ''
for (var i=0; i < theString.length; i++) {
let theUnicode = theString.charCodeAt(i).toString(16).toUpperCase()
while (theUnicode.length < 4) {
theUnicode = '0' + theUnicode
}
theUnicode = '\\u' + theUnicode
unicodeString += theUnicode
}
return unicodeString
}
Because node-exiftool
will be spawned with child_process.spawn
, when
testing, we will mock the spawn
method. To do that, use ctx.mockSpawn()
, and
access the process's mock with ctx.proc
. The process is an EventEmitter, and
will emit close
event when its stdin
is written with -stay_open\nfalse\n
.
ctx.mockSpawn()
const bin = 'echo'
const args = ['hello', 'world']
const options = {
cwd: HOME,
}
const proc = cp.spawn(bin, args, options)
assert.equal(ctx.proc, proc)
assert.equal(ctx.proc.args, { bin, args, options })
When args passed to cp.spawn
include -stay_open True
, it will automatically
push mocked date to the process's stderr
, simulating an opening echo.
Push some data to stderr
readable stream.
Push some data to stdout
readable stream.
An array with all data written to stdin
.
Arguments passed when calling child_process.spawn
command.
A test context is an object which is available to tests via ctx
argument. This is
implemented in zoroaster
test runner. It allows to abstract individual test contexts.
That makes maintanence of test files easier when they don't have to rely on global scope
of each other. You can create unique and specific tests contexts to be used in testing
of your application. Save time by reusing the code, and using tests as a tool, and not
the other way around.
To learn more about the idea of test contexts, read zoroaster documentation.
(c) Zoroaster 2017