#!/usr/bin/env python
'''Convert example documentation into jasmine test specs.
Reads from stdin, writes to stdout.

Input:
// ex. fold.contains(['a', 'b', 'c'], 1) -> false, explanation

Output:
it("fold.contains(['a', 'b', 'c'], 1) -> false, explanation", function() {
  expect(fold.contains(['a', 'b', 'c'], 1)).toBe(false);
});
'''

import argparse
import sys
import re

# Matches something like "// ex. fold.contains(['a', 'b', 'c'], 1) -> false"
PAT = re.compile(r'''
  ^\s*
  (
    //\s* (?# double slash comment)
    ex\.\s* (?# ex)
  )?
  (?P<test_case>
    (?P<funcall> .* )
    \s*->\s*
    (?P<result> .*? ) (?# non greedy * to allow explanation)
    (,[a-zA-Z0-9_ -]*)? (?# optional explanation, can only contain letters numbers, spaces, - or _)
  )
  $
''', re.VERBOSE | re.MULTILINE)

TEMPLATE_TO_BE = '''
it("{test_case}", function() {{
  expect({funcall}).toBe({result});
}});
'''

TEMPLATE_TO_EQUAL = '''
it("{test_case}", function() {{
  expect({funcall}).toEqual({result});
}});
'''

TEMPLATE_TO_THROW = '''
it("{test_case}", function() {{
  expect(function() {{ {funcall} }}).toThrow();
}});
'''

def main(args):
  TEMPLATE = TEMPLATE_TO_BE
  if args.equals:
    TEMPLATE = TEMPLATE_TO_EQUAL
  elif args.throws:
    TEMPLATE = TEMPLATE_TO_THROW

  for line in sys.stdin:
    line = line.strip()
    m = PAT.search(line)
    if m:
      print TEMPLATE.format(**m.groupdict()).strip()

if __name__ == '__main__':
  parser = argparse.ArgumentParser(description="Convert example documentation into jasmine test specs.")
  parser.add_argument("-t", "--throws", help="assert each case will throw an error",
                              action="store_true")
  parser.add_argument("-e", "--equals", help="use toEqual() to compare expected vs actual result",
                              action="store_true")
  args = parser.parse_args()
  main(args)
