watcher/test/hooks.js
2024-04-18 21:12:37 +02:00

168 lines
4.7 KiB
JavaScript

/* IMPORT */
import fs from 'node:fs';
import {setTimeout as delay} from 'node:timers/promises';
import Watcher from '../dist/watcher.js';
import Tree from './tree.js';
/* HELPERS */
let TREES = [];
/* MAIN */
//TODO: Use actual hooks, once those get fixed in "fava"
const before = async () => {
if ( fs.existsSync ( Tree.ROOT ) ) {
fs.rmdirSync ( Tree.ROOT, { recursive: true } );
}
TREES = await Promise.all ( Array ( 190 ).fill ().map ( async ( _, i ) => {
const tree = new Tree ( i );
await tree.build ();
return tree;
}));
await delay ( 5000 ); // Giving the filesystem enough time to chill
};
const beforeEach = t => {
const isEqual = ( a, b ) => JSON.stringify ( a ) === JSON.stringify ( b );
const prettyprint = value => JSON.stringify ( value, undefined, 2 );
t.context.normalizePaths = paths => {
return paths.map ( path => {
return Array.isArray ( path ) ? t.context.normalizePaths ( path ) : t.context.tree.path ( path );
});
};
t.context.hasWatchObjects = ( pollersNr, subwatchersNr, watchersNr ) => {
t.is ( t.context.watcher._pollers.size, pollersNr, 'pollers number' );
t.is ( t.context.watcher._subwatchers.size, subwatchersNr, 'subwatchers number' );
t.is ( Object.keys ( t.context.watcher._watchers ).map ( key => t.context.watcher._watchers[key] ).flat ().length, watchersNr, 'watchers number' );
};
t.context.deepEqualUnordered = ( a, b ) => {
t.is ( a.length, b.length );
t.true ( a.every ( item => {
const index = b.findIndex ( itemOther => isEqual ( item, itemOther ) );
if ( index === -1 ) return false;
b.splice ( index, 1 );
return true;
}), prettyprint ( [a, b] ) );
};
t.context.deepEqualUnorderedTuples = ( [a1, b1], [a2, b2] ) => {
t.is ( a1.length, b1.length );
t.is ( a1.length, a2.length );
t.is ( b1.length, b2.length );
t.true ( a1.every ( ( item, itemIndex ) => {
for ( let i = 0, l = a2.length; i < l; i++ ) {
if ( !isEqual ( item, a2[i] ) ) continue;
if ( !isEqual ( b1[itemIndex], b2[i] ) ) continue;
a1.splice ( itemIndex, 1 );
b1.splice ( itemIndex, 1 );
a2.splice ( i, 1 );
b2.splice ( i, 1 );
return true;
}
return false;
}), prettyprint ( [[a1, b1], [a2, b2]] ) );
};
t.context.deepEqualChanges = changes => {
t.deepEqual ( t.context.changes, t.context.normalizePaths ( changes ) );
};
t.context.deepEqualUnorderedChanges = changes => {
t.context.deepEqualUnordered ( t.context.changes, t.context.normalizePaths ( changes ) );
};
t.context.deepEqualResults = ( events, changes ) => {
t.deepEqual ( t.context.events, events );
t.deepEqual ( t.context.changes, t.context.normalizePaths ( changes ) );
t.context.watchReset ();
};
t.context.deepEqualUnorderedResults = ( events, changes ) => {
t.context.deepEqualUnorderedTuples ( [t.context.events, t.context.changes], [events, t.context.normalizePaths ( changes )] );
t.context.watchReset ();
};
t.context.watch = ( target, options = {}, handler = () => {}, filterer = () => true ) => {
const targets = t.context.normalizePaths ( Array.isArray ( target ) ? target : [target] );
t.context.events = [];
t.context.changes = [];
t.context.watcher = new Watcher ( targets, options, ( event, targetPath, targetPathNext ) => {
if ( !filterer ( event, targetPath ) ) return;
const change = targetPathNext ? [targetPath, targetPathNext] : targetPath;
t.context.events.push ( event );
t.context.changes.push ( change );
handler ( event, change );
});
};
t.context.watchForDirs = ( target, options, handler ) => {
const isDirEvent = event => event.endsWith ( 'Dir' );
t.context.watch ( target, options, handler, isDirEvent );
};
t.context.watchForFiles = ( target, options, handler ) => {
const isFileEvent = event => !event.endsWith ( 'Dir' );
t.context.watch ( target, options, handler, isFileEvent );
};
t.context.watchReset = () => {
t.context.events.length = 0;
t.context.changes.length = 0;
};
t.context.wait = {};
t.context.wait.close = () => {
return t.context.watcher._closeWait;
};
t.context.wait.ready = () => {
return t.context.watcher._readyWait;
};
t.context.wait.time = () => delay ( 1000 );
t.context.wait.longtime = () => delay ( 2000 );
t.context.wait.longlongtime = () => delay ( 3000 );
t.context.tree = TREES.pop ();
};
const afterEach = t => {
t.context.watcher.close ();
};
const withContext = fn => {
return async t => {
await beforeEach ( t );
await fn ( t );
await afterEach ( t );
};
};
/* EXPORT */
export {before, beforeEach, afterEach, withContext};