mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			126 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			126 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /**
 | ||
|  * Copyright (c) Microsoft Corporation.
 | ||
|  *
 | ||
|  * Licensed under the Apache License, Version 2.0 (the "License");
 | ||
|  * you may not use this file except in compliance with the License.
 | ||
|  * You may obtain a copy of the License at
 | ||
|  *
 | ||
|  * http://www.apache.org/licenses/LICENSE-2.0
 | ||
|  *
 | ||
|  * Unless required by applicable law or agreed to in writing, software
 | ||
|  * distributed under the License is distributed on an "AS IS" BASIS,
 | ||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||
|  * See the License for the specific language governing permissions and
 | ||
|  * limitations under the License.
 | ||
|  */
 | ||
| 
 | ||
| const Base = require('mocha/lib/reporters/base');
 | ||
| const constants = require('mocha/lib/runner').constants;
 | ||
| const colors = require('colors/safe');
 | ||
| const milliseconds = require('ms');
 | ||
| const { codeFrameColumns } = require('@babel/code-frame');
 | ||
| const path = require('path');
 | ||
| const fs = require('fs');
 | ||
| const os = require('os');
 | ||
| const terminalLink = require('terminal-link');
 | ||
| const StackUtils = require('stack-utils');
 | ||
| const stackUtils = new StackUtils();
 | ||
| class DotReporter extends Base {
 | ||
|   constructor(runner, options) {
 | ||
|     super(runner, options);
 | ||
| 
 | ||
|     process.on('SIGINT', async () => {
 | ||
|       this.epilogue();
 | ||
|       process.exit(130);
 | ||
|     });
 | ||
| 
 | ||
|     runner.on(constants.EVENT_TEST_PENDING, test => {
 | ||
|       process.stdout.write(colors.yellow('∘'))
 | ||
|     });
 | ||
| 
 | ||
|     runner.on(constants.EVENT_TEST_PASS, () => {
 | ||
|       process.stdout.write(colors.green('\u00B7'));
 | ||
|     });
 | ||
| 
 | ||
|     runner.on(constants.EVENT_TEST_FAIL, test => {
 | ||
|       if (test.duration >= test.timeout())
 | ||
|         process.stdout.write(colors.red('T'));
 | ||
|       else
 | ||
|         process.stdout.write(colors.red('F'));
 | ||
|     });
 | ||
| 
 | ||
|     runner.once(constants.EVENT_RUN_END, () => {
 | ||
|       process.stdout.write('\n');
 | ||
|       this.epilogue();
 | ||
|     });
 | ||
|   }
 | ||
| 
 | ||
|   epilogue() {
 | ||
|     console.log('');
 | ||
| 
 | ||
|     console.log(colors.green(`  ${this.stats.passes || 0} passing`) + colors.dim(` (${milliseconds(this.stats.duration)})`));  
 | ||
| 
 | ||
|     if (this.stats.pending)
 | ||
|       console.log(colors.yellow(`  ${this.stats.pending} skipped`));
 | ||
| 
 | ||
|     if (this.stats.failures) {  
 | ||
|       console.log(colors.red(`  ${this.stats.failures} failing`));
 | ||
|       console.log('');
 | ||
|       this.failures.forEach((failure, index) => {
 | ||
|         const relativePath = path.relative(process.cwd(), failure.file);
 | ||
|         const header = `  ${index +1}. ${terminalLink(relativePath, `file://${os.hostname()}${failure.file}`)} › ${failure.title}`;
 | ||
|         console.log(colors.bold.red(header));
 | ||
|         const stack = failure.err.stack;
 | ||
|         if (stack) {
 | ||
|           console.log('');
 | ||
|           const messageLocation = failure.err.stack.indexOf(failure.err.message);
 | ||
|           const preamble = failure.err.stack.substring(0, messageLocation + failure.err.message.length);
 | ||
|           console.log(indent(preamble, '    '));
 | ||
|           const position = positionInFile(stack, failure.file);
 | ||
|           if (position) {
 | ||
|             const source = fs.readFileSync(failure.file, 'utf8');
 | ||
|             console.log('');
 | ||
|             console.log(indent(codeFrameColumns(source, {
 | ||
|                 start: position,
 | ||
|               },
 | ||
|               { highlightCode: true}
 | ||
|             ), '    '));
 | ||
|           }
 | ||
|           console.log('');
 | ||
|           console.log(indent(colors.dim(stack.substring(preamble.length + 1)), '    '));
 | ||
|         } else {
 | ||
|           console.log('');
 | ||
|           console.log(indent(String(failure.err), '    '));
 | ||
|         }
 | ||
|         console.log('');
 | ||
|       });
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * @param {string} lines 
 | ||
|  * @param {string} tab 
 | ||
|  */
 | ||
| function indent(lines, tab) {
 | ||
|   return lines.replace(/^/gm, tab);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * @param {string} stack 
 | ||
|  * @param {string} file 
 | ||
|  * @return {{column: number, line: number}}
 | ||
|  */
 | ||
| function positionInFile(stack, file) {
 | ||
|   for (const line of stack.split('\n')) {
 | ||
|     const parsed = stackUtils.parseLine(line);
 | ||
|     if (!parsed)
 | ||
|       continue;
 | ||
|     if (path.resolve(process.cwd(), parsed.file) === file)
 | ||
|       return {column: parsed.column, line: parsed.line};
 | ||
|   }
 | ||
|   return null;
 | ||
| }
 | ||
| 
 | ||
| module.exports = DotReporter;
 | 
