Custom Protractor Flake shard parser

PR #45 on Protractor Flake added the ability to specify custom parsers. On my project we’re sharding (running multiple instances of) Protractor and using the following parser to re-run only the failing spec files.

You’ll want to replace the /test/functional/specs/ and the browser name (chrome) below with your actual values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
const _ = require('lodash');
 
// If only one spec file fails, on the next re-run, we don't get the filename on the output. So
// if it fails again, we need re-use the filename from the previous run
let previousSpecFileNames = [];
 
module.exports = {
  parse: function (protractorTestOutput) {
    if (previousSpecFileNames.length === 1) {
      return previousSpecFileNames;
    }
 
    const lines = protractorTestOutput.split(`\n`);
    // At the end of the output there's a summary of which shards failed
    const failedLines = lines.filter(line =>
      line.startsWith('[launcher] chrome')
      && line.includes('failed')
      && line.includes('test(s)'));
 
    // regex matches #number and #number-number (ie #1 or #1-1, #1-2, #1-3...)
    const testNumberRegExp = new RegExp(/#[0-9](-[0-9]+)?/);
 
    const failedSpecsLines = failedLines.map(failedLine => {
      const match = testNumberRegExp.exec(failedLine);
 
      if (match) {
        // Lines with "#number-number ]" (space followed by closing bracket) and "Specs: "
        return lines.filter(line => line.includes(`${match[0]}] `) && line.includes('Specs: '));
      }
 
      return null;
    }).reduce(function (a, b) { // Flatten the array
      return a.concat(b);
    }, []);
 
    const specFileNames = _.compact(failedSpecsLines).map(line => {
      const startingPathPosition = line.indexOf('/test/functional/specs/');
      return line.substr(startingPathPosition + 1);
    });
 
    previousSpecFileNames = specFileNames;
 
    return specFileNames;
  },
 
  name: 'Your custom parser name',
};