11cb0ef41Sopenharmony_ci'use strict'; 21cb0ef41Sopenharmony_ciconst common = require('../common'); 31cb0ef41Sopenharmony_ci 41cb0ef41Sopenharmony_ciif (common.isIBMi) 51cb0ef41Sopenharmony_ci common.skip('IBMi does not support `fs.watch()`'); 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci// Tests if `filename` is provided to watcher on supported platforms 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ciconst fs = require('fs'); 101cb0ef41Sopenharmony_ciconst assert = require('assert'); 111cb0ef41Sopenharmony_ciconst { join } = require('path'); 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_ciclass WatchTestCase { 141cb0ef41Sopenharmony_ci constructor(shouldInclude, dirName, fileName, field) { 151cb0ef41Sopenharmony_ci this.dirName = dirName; 161cb0ef41Sopenharmony_ci this.fileName = fileName; 171cb0ef41Sopenharmony_ci this.field = field; 181cb0ef41Sopenharmony_ci this.shouldSkip = !shouldInclude; 191cb0ef41Sopenharmony_ci } 201cb0ef41Sopenharmony_ci get dirPath() { return join(tmpdir.path, this.dirName); } 211cb0ef41Sopenharmony_ci get filePath() { return join(this.dirPath, this.fileName); } 221cb0ef41Sopenharmony_ci} 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_ciconst cases = [ 251cb0ef41Sopenharmony_ci // Watch on a file should callback with a filename on supported systems 261cb0ef41Sopenharmony_ci new WatchTestCase( 271cb0ef41Sopenharmony_ci common.isLinux || common.isOSX || common.isWindows || common.isAIX, 281cb0ef41Sopenharmony_ci 'watch1', 291cb0ef41Sopenharmony_ci 'foo', 301cb0ef41Sopenharmony_ci 'filePath' 311cb0ef41Sopenharmony_ci ), 321cb0ef41Sopenharmony_ci // Watch on a directory should callback with a filename on supported systems 331cb0ef41Sopenharmony_ci new WatchTestCase( 341cb0ef41Sopenharmony_ci common.isLinux || common.isOSX || common.isWindows, 351cb0ef41Sopenharmony_ci 'watch2', 361cb0ef41Sopenharmony_ci 'bar', 371cb0ef41Sopenharmony_ci 'dirPath' 381cb0ef41Sopenharmony_ci ), 391cb0ef41Sopenharmony_ci]; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_ciconst tmpdir = require('../common/tmpdir'); 421cb0ef41Sopenharmony_citmpdir.refresh(); 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cifor (const testCase of cases) { 451cb0ef41Sopenharmony_ci if (testCase.shouldSkip) continue; 461cb0ef41Sopenharmony_ci fs.mkdirSync(testCase.dirPath); 471cb0ef41Sopenharmony_ci // Long content so it's actually flushed. 481cb0ef41Sopenharmony_ci const content1 = Date.now() + testCase.fileName.toLowerCase().repeat(1e4); 491cb0ef41Sopenharmony_ci fs.writeFileSync(testCase.filePath, content1); 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci let interval; 521cb0ef41Sopenharmony_ci const pathToWatch = testCase[testCase.field]; 531cb0ef41Sopenharmony_ci const watcher = fs.watch(pathToWatch); 541cb0ef41Sopenharmony_ci watcher.on('error', (err) => { 551cb0ef41Sopenharmony_ci if (interval) { 561cb0ef41Sopenharmony_ci clearInterval(interval); 571cb0ef41Sopenharmony_ci interval = null; 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci assert.fail(err); 601cb0ef41Sopenharmony_ci }); 611cb0ef41Sopenharmony_ci watcher.on('close', common.mustCall(() => { 621cb0ef41Sopenharmony_ci watcher.close(); // Closing a closed watcher should be a noop 631cb0ef41Sopenharmony_ci })); 641cb0ef41Sopenharmony_ci watcher.on('change', common.mustCall(function(eventType, argFilename) { 651cb0ef41Sopenharmony_ci if (interval) { 661cb0ef41Sopenharmony_ci clearInterval(interval); 671cb0ef41Sopenharmony_ci interval = null; 681cb0ef41Sopenharmony_ci } 691cb0ef41Sopenharmony_ci if (common.isOSX) 701cb0ef41Sopenharmony_ci assert.strictEqual(['rename', 'change'].includes(eventType), true); 711cb0ef41Sopenharmony_ci else 721cb0ef41Sopenharmony_ci assert.strictEqual(eventType, 'change'); 731cb0ef41Sopenharmony_ci assert.strictEqual(argFilename, testCase.fileName); 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci watcher.close(); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci // We document that watchers cannot be used anymore when it's closed, 781cb0ef41Sopenharmony_ci // here we turn the methods into noops instead of throwing 791cb0ef41Sopenharmony_ci watcher.close(); // Closing a closed watcher should be a noop 801cb0ef41Sopenharmony_ci })); 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci // Long content so it's actually flushed. toUpperCase so there's real change. 831cb0ef41Sopenharmony_ci const content2 = Date.now() + testCase.fileName.toUpperCase().repeat(1e4); 841cb0ef41Sopenharmony_ci interval = setInterval(() => { 851cb0ef41Sopenharmony_ci fs.writeFileSync(testCase.filePath, ''); 861cb0ef41Sopenharmony_ci fs.writeFileSync(testCase.filePath, content2); 871cb0ef41Sopenharmony_ci }, 100); 881cb0ef41Sopenharmony_ci} 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci[false, 1, {}, [], null, undefined].forEach((input) => { 911cb0ef41Sopenharmony_ci assert.throws( 921cb0ef41Sopenharmony_ci () => fs.watch(input, common.mustNotCall()), 931cb0ef41Sopenharmony_ci { 941cb0ef41Sopenharmony_ci code: 'ERR_INVALID_ARG_TYPE', 951cb0ef41Sopenharmony_ci name: 'TypeError' 961cb0ef41Sopenharmony_ci } 971cb0ef41Sopenharmony_ci ); 981cb0ef41Sopenharmony_ci}); 99