-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
9 changed files
with
242 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
const chalk = require('chalk'); | ||
const customChalk = new chalk.Instance({level: 1}); | ||
|
||
console.log("__disable_ansi_serialization"); | ||
|
||
// eslint-disable-next-line prefer-template | ||
console.log(customChalk.blue('Hello') + ' World' + customChalk.red('!')); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import fs from 'fs' | ||
import {getUserCodeFrame} from '../get-user-code-frame' | ||
|
||
jest.mock('fs', () => ({ | ||
// We setup the contents of a sample file | ||
readFileSync: jest.fn( | ||
() => ` | ||
import {screen} from '@testing-library/dom' | ||
it('renders', () => { | ||
document.body.appendChild( | ||
document.createTextNode('Hello world') | ||
) | ||
screen.debug() | ||
expect(screen.getByText('Hello world')).toBeInTheDocument() | ||
}) | ||
`, | ||
), | ||
})) | ||
|
||
const userStackFrame = 'at somethingWrong (/sample-error/error-example.js:7:14)' | ||
|
||
let globalErrorMock | ||
|
||
beforeEach(() => { | ||
// Mock global.Error so we can setup our own stack messages | ||
globalErrorMock = jest.spyOn(global, 'Error') | ||
}) | ||
|
||
afterEach(() => { | ||
global.Error.mockRestore() | ||
}) | ||
|
||
test('it returns only user code frame when code frames from node_modules are first', () => { | ||
const stack = `Error: Kaboom | ||
at Object.<anonymous> (/sample-error/node_modules/@es2050/console/build/index.js:4:10) | ||
${userStackFrame} | ||
` | ||
globalErrorMock.mockImplementationOnce(() => ({stack})) | ||
const userTrace = getUserCodeFrame(stack) | ||
|
||
expect(userTrace).toMatchInlineSnapshot(` | ||
/sample-error/error-example.js:7:14 | ||
5 | document.createTextNode('Hello world') | ||
6 | ) | ||
> 7 | screen.debug() | ||
| ^ | ||
`) | ||
}) | ||
|
||
test('it returns only user code frame when node code frames are present afterwards', () => { | ||
const stack = `Error: Kaboom | ||
at Object.<anonymous> (/sample-error/node_modules/@es2050/console/build/index.js:4:10) | ||
${userStackFrame} | ||
at Object.<anonymous> (/sample-error/error-example.js:14:1) | ||
at internal/main/run_main_module.js:17:47 | ||
` | ||
globalErrorMock.mockImplementationOnce(() => ({stack})) | ||
const userTrace = getUserCodeFrame() | ||
|
||
expect(userTrace).toMatchInlineSnapshot(` | ||
/sample-error/error-example.js:7:14 | ||
5 | document.createTextNode('Hello world') | ||
6 | ) | ||
> 7 | screen.debug() | ||
| ^ | ||
`) | ||
}) | ||
|
||
test("it returns empty string if file from code frame can't be read", () => { | ||
// Make fire read purposely fail | ||
fs.readFileSync.mockImplementationOnce(() => { | ||
throw Error() | ||
}) | ||
const stack = `Error: Kaboom | ||
${userStackFrame} | ||
` | ||
globalErrorMock.mockImplementationOnce(() => ({stack})) | ||
|
||
expect(getUserCodeFrame(stack)).toEqual('') | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
const {resolve} = require('path') | ||
const {render} = require('../pure') | ||
const {prettyCLI} = require('../pretty-cli') | ||
|
||
|
||
test('Should pretty print with ANSI codes properly', async () => { | ||
const instance = await render('node', [ | ||
resolve(__dirname, './execute-scripts/log-output.js'), | ||
]) | ||
|
||
await instance.findByText('Hello') | ||
|
||
expect(prettyCLI(instance, 9000)).toMatchInlineSnapshot(` | ||
__disable_ansi_serialization | ||
[34mHello[39m World[31m![39m | ||
`) | ||
}) | ||
|
||
test('Should escape ANSI codes properly when sliced too thin', async () => { | ||
const instance = await render('node', [ | ||
resolve(__dirname, './execute-scripts/log-output.js'), | ||
]) | ||
|
||
await instance.findByText('Hello') | ||
|
||
expect(prettyCLI(instance, 30)).toMatchInlineSnapshot(` | ||
__disable_ansi_serialization | ||
[34mH[39m | ||
`) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
// We try to load node dependencies | ||
let chalk = null | ||
let readFileSync = null | ||
let codeFrameColumns = null | ||
|
||
try { | ||
const nodeRequire = module && module.require | ||
|
||
readFileSync = nodeRequire.call(module, 'fs').readFileSync | ||
codeFrameColumns = nodeRequire.call( | ||
module, | ||
'@babel/code-frame', | ||
).codeFrameColumns | ||
chalk = nodeRequire.call(module, 'chalk') | ||
} catch { | ||
// We're in a browser environment | ||
} | ||
|
||
// frame has the form "at myMethod (location/to/my/file.js:10:2)" | ||
function getCodeFrame(frame) { | ||
const locationStart = frame.indexOf('(') + 1 | ||
const locationEnd = frame.indexOf(')') | ||
const frameLocation = frame.slice(locationStart, locationEnd) | ||
|
||
const frameLocationElements = frameLocation.split(':') | ||
const [filename, line, column] = [ | ||
frameLocationElements[0], | ||
parseInt(frameLocationElements[1], 10), | ||
parseInt(frameLocationElements[2], 10), | ||
] | ||
|
||
let rawFileContents = '' | ||
try { | ||
rawFileContents = readFileSync(filename, 'utf-8') | ||
} catch { | ||
return '' | ||
} | ||
|
||
const codeFrame = codeFrameColumns( | ||
rawFileContents, | ||
{ | ||
start: {line, column}, | ||
}, | ||
{ | ||
highlightCode: true, | ||
linesBelow: 0, | ||
}, | ||
) | ||
return `${chalk.dim(frameLocation)}\n${codeFrame}\n` | ||
} | ||
|
||
function getUserCodeFrame() { | ||
// If we couldn't load dependencies, we can't generate the user trace | ||
/* istanbul ignore next */ | ||
if (!readFileSync || !codeFrameColumns) { | ||
return '' | ||
} | ||
const err = new Error() | ||
const firstClientCodeFrame = err.stack | ||
.split('\n') | ||
.slice(1) // Remove first line which has the form "Error: TypeError" | ||
.find(frame => !frame.includes('node_modules/')) // Ignore frames from 3rd party libraries | ||
|
||
return getCodeFrame(firstClientCodeFrame) | ||
} | ||
|
||
export {getUserCodeFrame} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import sliceAnsi from 'slice-ansi'; | ||
import {getUserCodeFrame} from './get-user-code-frame' | ||
|
||
function prettyCLI(testInstance, maxLength) { | ||
if (typeof maxLength !== 'number') { | ||
maxLength = | ||
(typeof process !== 'undefined' && process.env.DEBUG_PRINT_LIMIT) || 7000 | ||
} | ||
|
||
if (maxLength === 0) { | ||
return '' | ||
} | ||
|
||
if (!('stdoutArr' in testInstance)) { | ||
throw new TypeError( | ||
`Expected an instance but got ${testInstance}`, | ||
) | ||
} | ||
|
||
const outStr = testInstance.stdoutArr.join('\n'); | ||
|
||
// eslint-disable-next-line no-negated-condition | ||
return maxLength !== undefined && outStr.length > maxLength | ||
? sliceAnsi(outStr, 0, maxLength) | ||
: outStr | ||
} | ||
|
||
const logCLI = (...args) => { | ||
const userCodeFrame = getUserCodeFrame() | ||
if (userCodeFrame) { | ||
process.stdout.write(`${prettyCLI(...args)}\n\n${userCodeFrame}`) | ||
} else { | ||
process.stdout.write(prettyCLI(...args)) | ||
} | ||
} | ||
|
||
export {prettyCLI, logCLI} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters