Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"request": "launch",
"name": "Run Mocha tests",
"program": "${workspaceRoot}/packages/build/node_modules/mocha/bin/_mocha",
"runtimeArgs": ["-r", "${workspaceRoot}/packages/build/node_modules/source-map-support/register"],
"cwd": "${workspaceRoot}",
"args": [
"--config",
Expand All @@ -18,6 +19,25 @@
"0"
]
},
{
"type": "node",
"request": "launch",
"name": "Debug Current Test File",
"program": "${workspaceRoot}/bin/mocha-current-file",
"runtimeArgs": ["-r", "${workspaceRoot}/packages/build/node_modules/source-map-support/register"],
"cwd": "${workspaceRoot}",
"args": [
"--config",
"${workspaceRoot}/packages/build/config/.mocharc.json",
"-t",
"0",
"${file}"
],
// This ensures vscode won't set breakpoints until after sourcemaps
// have been loaded for the file. Important when your tests are compiled
// from typescript.
"disableOptimisticBPs": true,
},
{
"type": "node",
"request": "attach",
Expand Down
80 changes: 80 additions & 0 deletions bin/mocha-current-file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env node

// Copyright IBM Corp. 2020. All Rights Reserved.
// Node module: @loopback-next
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

/*
================================================================================
This is used in the launch.json to enable you to debug a test file written in
typescript. This function attempts to convert the passed typescript file to
the best-guess output javascript file.

It walks up the filesystem from the current file, stops at package.json, and
looks in `dist`

Ideally, we could somehow use the typescript compiler and tsconfig.json to get
the explicit output file instead of trying to guess it, but there might be
overhead.

Ex:
```jsonc
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Debug Current Test File",
"program": "${workspaceRoot}/bin/mocha-current-file",
"runtimeArgs": ["-r", "${workspaceRoot}/packages/build/node_modules/source-map-support/register"],
"cwd": "${workspaceRoot}",
"autoAttachChildProcesses": true,
"args": [
"--config",
"${workspaceRoot}/packages/build/config/.mocharc.json",
"-t",
"0",
"${file}"
],
"disableOptimisticBPs": true
}
]
}
```
================================================================================
*/

'use strict';
const path = require('path');
const fs = require('fs');

function findDistFile(filename) {
const absolutePath = path.resolve(filename);
const systemRoot = path.parse(absolutePath).root;
let currentDir = path.dirname(absolutePath);

let isPackageRoot = fs.existsSync(path.resolve(currentDir, 'package.json'));
while (!isPackageRoot) {
if (path.dirname(currentDir) === systemRoot) {
throw new Error(
`Could not find a package.json file in the path heirarchy of ${absolutePath}`,
);
}
currentDir = path.join(currentDir, '..');
isPackageRoot = fs.existsSync(path.resolve(currentDir, 'package.json'));
}
const base = path.resolve(currentDir);
const relative = path.relative(currentDir, absolutePath);
const resultPath = relative.replace(/^src/, 'dist').replace(/\.ts$/, '.js');
return path.resolve(base, resultPath);
}
Copy link
Contributor

@raymondfeng raymondfeng Mar 6, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: the current code has a theoretical possibility of infinite loop as it does not test the root of a file system. A more robust implementation can be:

let pkgFile = path.resolve(filename, '../package.json');

// Find root directory of the file system
const root = path.parse(pkgFile).root;

while (!fs.existsSync(pkgFile)) {
  if (path.dirname(pkgFile) === root) {
    // We reach the root of file system
    pkgFile = undefined;
    break;
  }
  // Try the parent directory level package.json
  pkgFile = path.resolve(pkgFile, '../../package.json');
}

if (!pkgFile) return filename; // Or throw an error
const projectRoot = path.dirname(pkgFile);
const relative = path.relative(projectRoot, path.resolve(filename));
const jsFilePath = relative.replace(/^src/, 'dist').replace(/\.ts$/, '.js');
return path.resolve(projectRoot, jsFilePath);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a small change to the current function, and tested it by invoking this cli against both a test file inside of the loopback-next workspace, and also a fake.test.js file that has no package.json file in it's filesystem heirarchy


const newFile = findDistFile(process.argv.splice(-1)[0]);

if (newFile) {
require('../packages/build/node_modules/mocha/lib/cli').main(
[...process.argv, newFile].slice(2),
);
}