index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import chokidar from 'chokidar';
  2. import * as path from 'path';
  3. import {fileURLToPath} from 'url';
  4. import {quickLoadAllFromYAML} from '../../src/data/yaml.js';
  5. import {isMain} from '../../src/util/node-utils.js';
  6. import {getContextAssignments} from '../../src/repl.js';
  7. import {
  8. color,
  9. logError,
  10. logInfo,
  11. logWarn,
  12. parseOptions,
  13. } from '../../src/util/cli.js';
  14. import {
  15. bindOpts,
  16. showAggregate,
  17. } from '../../src/util/sugar.js';
  18. async function main() {
  19. const miscOptions = await parseOptions(process.argv.slice(2), {
  20. 'data-path': {
  21. type: 'value',
  22. },
  23. });
  24. const dataPath = miscOptions['data-path'] || process.env.HSMUSIC_DATA;
  25. if (!dataPath) {
  26. logError`Expected --data-path option or HSMUSIC_DATA to be set`;
  27. return;
  28. }
  29. console.log(`HSMusic automated data tests`);
  30. console.log(`${color.bright(color.yellow(`:star:`))} Now featuring quick-reloading! ${color.bright(color.cyan(`:earth:`))}`);
  31. // Watch adjacent files in data-tests directory
  32. const metaPath = fileURLToPath(import.meta.url);
  33. const metaDirname = path.dirname(metaPath);
  34. const watcher = chokidar.watch(metaDirname);
  35. const wikiData = await quickLoadAllFromYAML(dataPath, {
  36. showAggregate: bindOpts(showAggregate, {
  37. showTraces: false,
  38. }),
  39. });
  40. const context = await getContextAssignments({
  41. wikiData,
  42. });
  43. let resolveNext;
  44. const queue = [];
  45. watcher.on('all', (event, path) => {
  46. if (!['add', 'change'].includes(event)) return;
  47. if (path === metaPath) return;
  48. if (resolveNext) {
  49. resolveNext(path);
  50. } else if (!queue.includes(path)) {
  51. queue.push(path);
  52. }
  53. });
  54. logInfo`Awaiting file changes.`;
  55. /* eslint-disable-next-line no-constant-condition */
  56. while (true) {
  57. const testPath = (queue.length
  58. ? queue.shift()
  59. : await new Promise(resolve => {
  60. resolveNext = resolve;
  61. }));
  62. resolveNext = null;
  63. const shortPath = path.basename(testPath);
  64. logInfo`Path updated: ${shortPath} - running this test!`;
  65. let imp;
  66. try {
  67. imp = await import(`${testPath}?${Date.now()}`)
  68. } catch (error) {
  69. logWarn`Failed to import ${shortPath} - ${error.constructor.name} details below:`;
  70. console.error(error);
  71. continue;
  72. }
  73. const {default: testFn} = imp;
  74. if (!testFn) {
  75. logWarn`No default export for ${shortPath}`;
  76. logWarn`Skipping this test for now!`;
  77. continue;
  78. }
  79. if (typeof testFn !== 'function') {
  80. logWarn`Default export for ${shortPath} is ${typeof testFn}, not function`;
  81. logWarn`Skipping this test for now!`;
  82. continue;
  83. }
  84. try {
  85. await testFn(context);
  86. } catch (error) {
  87. showAggregate(error, {
  88. pathToFileURL: f => path.relative(metaDirname, fileURLToPath(f)),
  89. });
  90. }
  91. }
  92. }
  93. if (isMain(import.meta.url)) {
  94. main().catch((error) => {
  95. if (error instanceof AggregateError) {
  96. showAggregate(error);
  97. } else {
  98. console.error(error);
  99. }
  100. });
  101. }