11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst ArrayStream = require('../common/arraystream');
51cb0ef41Sopenharmony_ciconst fixtures = require('../common/fixtures');
61cb0ef41Sopenharmony_ciconst assert = require('assert');
71cb0ef41Sopenharmony_ciconst { builtinModules } = require('module');
81cb0ef41Sopenharmony_ciconst publicModules = builtinModules.filter((lib) => !lib.startsWith('_'));
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ciif (!common.isMainThread)
111cb0ef41Sopenharmony_ci  common.skip('process.chdir is not available in Workers');
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_ci// We have to change the directory to ../fixtures before requiring repl
141cb0ef41Sopenharmony_ci// in order to make the tests for completion of node_modules work properly
151cb0ef41Sopenharmony_ci// since repl modifies module.paths.
161cb0ef41Sopenharmony_ciprocess.chdir(fixtures.fixturesDir);
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_ciconst repl = require('repl');
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciconst putIn = new ArrayStream();
211cb0ef41Sopenharmony_ciconst testMe = repl.start({
221cb0ef41Sopenharmony_ci  prompt: '',
231cb0ef41Sopenharmony_ci  input: putIn,
241cb0ef41Sopenharmony_ci  output: process.stdout,
251cb0ef41Sopenharmony_ci  allowBlockingCompletions: true
261cb0ef41Sopenharmony_ci});
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ci// Some errors are passed to the domain, but do not callback
291cb0ef41Sopenharmony_citestMe._domain.on('error', assert.ifError);
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci// Tab complete provides built in libs for import()
321cb0ef41Sopenharmony_citestMe.complete('import(\'', common.mustCall((error, data) => {
331cb0ef41Sopenharmony_ci  assert.strictEqual(error, null);
341cb0ef41Sopenharmony_ci  publicModules.forEach((lib) => {
351cb0ef41Sopenharmony_ci    assert(
361cb0ef41Sopenharmony_ci      data[0].includes(lib) && data[0].includes(`node:${lib}`),
371cb0ef41Sopenharmony_ci      `${lib} not found`,
381cb0ef41Sopenharmony_ci    );
391cb0ef41Sopenharmony_ci  });
401cb0ef41Sopenharmony_ci  const newModule = 'foobar';
411cb0ef41Sopenharmony_ci  assert(!builtinModules.includes(newModule));
421cb0ef41Sopenharmony_ci  repl.builtinModules.push(newModule);
431cb0ef41Sopenharmony_ci  testMe.complete('import(\'', common.mustCall((_, [modules]) => {
441cb0ef41Sopenharmony_ci    assert.strictEqual(data[0].length + 1, modules.length);
451cb0ef41Sopenharmony_ci    assert(modules.includes(newModule) &&
461cb0ef41Sopenharmony_ci      !modules.includes(`node:${newModule}`));
471cb0ef41Sopenharmony_ci  }));
481cb0ef41Sopenharmony_ci}));
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_citestMe.complete("import\t( 'n", common.mustCall((error, data) => {
511cb0ef41Sopenharmony_ci  assert.strictEqual(error, null);
521cb0ef41Sopenharmony_ci  assert.strictEqual(data.length, 2);
531cb0ef41Sopenharmony_ci  assert.strictEqual(data[1], 'n');
541cb0ef41Sopenharmony_ci  const completions = data[0];
551cb0ef41Sopenharmony_ci  // import(...) completions include `node:` URL modules:
561cb0ef41Sopenharmony_ci  let lastIndex = -1;
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci  publicModules.forEach((lib, index) => {
591cb0ef41Sopenharmony_ci    lastIndex = completions.indexOf(`node:${lib}`);
601cb0ef41Sopenharmony_ci    assert.notStrictEqual(lastIndex, -1);
611cb0ef41Sopenharmony_ci  });
621cb0ef41Sopenharmony_ci  assert.strictEqual(completions[lastIndex + 1], '');
631cb0ef41Sopenharmony_ci  // There is only one Node.js module that starts with n:
641cb0ef41Sopenharmony_ci  assert.strictEqual(completions[lastIndex + 2], 'net');
651cb0ef41Sopenharmony_ci  assert.strictEqual(completions[lastIndex + 3], '');
661cb0ef41Sopenharmony_ci  // It's possible to pick up non-core modules too
671cb0ef41Sopenharmony_ci  completions.slice(lastIndex + 4).forEach((completion) => {
681cb0ef41Sopenharmony_ci    assert.match(completion, /^n/);
691cb0ef41Sopenharmony_ci  });
701cb0ef41Sopenharmony_ci}));
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci{
731cb0ef41Sopenharmony_ci  const expected = ['@nodejsscope', '@nodejsscope/'];
741cb0ef41Sopenharmony_ci  // Import calls should handle all types of quotation marks.
751cb0ef41Sopenharmony_ci  for (const quotationMark of ["'", '"', '`']) {
761cb0ef41Sopenharmony_ci    putIn.run(['.clear']);
771cb0ef41Sopenharmony_ci    testMe.complete('import(`@nodejs', common.mustCall((err, data) => {
781cb0ef41Sopenharmony_ci      assert.strictEqual(err, null);
791cb0ef41Sopenharmony_ci      assert.deepStrictEqual(data, [expected, '@nodejs']);
801cb0ef41Sopenharmony_ci    }));
811cb0ef41Sopenharmony_ci
821cb0ef41Sopenharmony_ci    putIn.run(['.clear']);
831cb0ef41Sopenharmony_ci    // Completions should not be greedy in case the quotation ends.
841cb0ef41Sopenharmony_ci    const input = `import(${quotationMark}@nodejsscope${quotationMark}`;
851cb0ef41Sopenharmony_ci    testMe.complete(input, common.mustCall((err, data) => {
861cb0ef41Sopenharmony_ci      assert.strictEqual(err, null);
871cb0ef41Sopenharmony_ci      assert.deepStrictEqual(data, [[], undefined]);
881cb0ef41Sopenharmony_ci    }));
891cb0ef41Sopenharmony_ci  }
901cb0ef41Sopenharmony_ci}
911cb0ef41Sopenharmony_ci
921cb0ef41Sopenharmony_ci{
931cb0ef41Sopenharmony_ci  putIn.run(['.clear']);
941cb0ef41Sopenharmony_ci  // Completions should find modules and handle whitespace after the opening
951cb0ef41Sopenharmony_ci  // bracket.
961cb0ef41Sopenharmony_ci  testMe.complete('import \t("no_ind', common.mustCall((err, data) => {
971cb0ef41Sopenharmony_ci    assert.strictEqual(err, null);
981cb0ef41Sopenharmony_ci    assert.deepStrictEqual(data, [['no_index', 'no_index/'], 'no_ind']);
991cb0ef41Sopenharmony_ci  }));
1001cb0ef41Sopenharmony_ci}
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci// Test tab completion for import() relative to the current directory
1031cb0ef41Sopenharmony_ci{
1041cb0ef41Sopenharmony_ci  putIn.run(['.clear']);
1051cb0ef41Sopenharmony_ci
1061cb0ef41Sopenharmony_ci  const cwd = process.cwd();
1071cb0ef41Sopenharmony_ci  process.chdir(__dirname);
1081cb0ef41Sopenharmony_ci
1091cb0ef41Sopenharmony_ci  ['import(\'.', 'import(".'].forEach((input) => {
1101cb0ef41Sopenharmony_ci    testMe.complete(input, common.mustCall((err, data) => {
1111cb0ef41Sopenharmony_ci      assert.strictEqual(err, null);
1121cb0ef41Sopenharmony_ci      assert.strictEqual(data.length, 2);
1131cb0ef41Sopenharmony_ci      assert.strictEqual(data[1], '.');
1141cb0ef41Sopenharmony_ci      assert.strictEqual(data[0].length, 2);
1151cb0ef41Sopenharmony_ci      assert.ok(data[0].includes('./'));
1161cb0ef41Sopenharmony_ci      assert.ok(data[0].includes('../'));
1171cb0ef41Sopenharmony_ci    }));
1181cb0ef41Sopenharmony_ci  });
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  ['import(\'..', 'import("..'].forEach((input) => {
1211cb0ef41Sopenharmony_ci    testMe.complete(input, common.mustCall((err, data) => {
1221cb0ef41Sopenharmony_ci      assert.strictEqual(err, null);
1231cb0ef41Sopenharmony_ci      assert.deepStrictEqual(data, [['../'], '..']);
1241cb0ef41Sopenharmony_ci    }));
1251cb0ef41Sopenharmony_ci  });
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  ['./', './test-'].forEach((path) => {
1281cb0ef41Sopenharmony_ci    [`import('${path}`, `import("${path}`].forEach((input) => {
1291cb0ef41Sopenharmony_ci      testMe.complete(input, common.mustCall((err, data) => {
1301cb0ef41Sopenharmony_ci        assert.strictEqual(err, null);
1311cb0ef41Sopenharmony_ci        assert.strictEqual(data.length, 2);
1321cb0ef41Sopenharmony_ci        assert.strictEqual(data[1], path);
1331cb0ef41Sopenharmony_ci        assert.ok(data[0].includes('./test-repl-tab-complete.js'));
1341cb0ef41Sopenharmony_ci      }));
1351cb0ef41Sopenharmony_ci    });
1361cb0ef41Sopenharmony_ci  });
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  ['../parallel/', '../parallel/test-'].forEach((path) => {
1391cb0ef41Sopenharmony_ci    [`import('${path}`, `import("${path}`].forEach((input) => {
1401cb0ef41Sopenharmony_ci      testMe.complete(input, common.mustCall((err, data) => {
1411cb0ef41Sopenharmony_ci        assert.strictEqual(err, null);
1421cb0ef41Sopenharmony_ci        assert.strictEqual(data.length, 2);
1431cb0ef41Sopenharmony_ci        assert.strictEqual(data[1], path);
1441cb0ef41Sopenharmony_ci        assert.ok(data[0].includes('../parallel/test-repl-tab-complete.js'));
1451cb0ef41Sopenharmony_ci      }));
1461cb0ef41Sopenharmony_ci    });
1471cb0ef41Sopenharmony_ci  });
1481cb0ef41Sopenharmony_ci
1491cb0ef41Sopenharmony_ci  {
1501cb0ef41Sopenharmony_ci    const path = '../fixtures/repl-folder-extensions/f';
1511cb0ef41Sopenharmony_ci    testMe.complete(`import('${path}`, common.mustSucceed((data) => {
1521cb0ef41Sopenharmony_ci      assert.strictEqual(data.length, 2);
1531cb0ef41Sopenharmony_ci      assert.strictEqual(data[1], path);
1541cb0ef41Sopenharmony_ci      assert.ok(data[0].includes(
1551cb0ef41Sopenharmony_ci        '../fixtures/repl-folder-extensions/foo.js/'));
1561cb0ef41Sopenharmony_ci    }));
1571cb0ef41Sopenharmony_ci  }
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci  process.chdir(cwd);
1601cb0ef41Sopenharmony_ci}
161