168 lines
4.7 KiB
JavaScript
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};
|