const assert = require('assert');
const fs = require('fs');
const path = require('path');
const specMarkdown = require('../');

const shouldRecord = Boolean(process.env.RECORD);

runTests([
  ['../README.md', 'readme/ast.json', 'readme/output.html'],
  ['simple-header/input.md', 'simple-header/ast.json', 'simple-header/output.html'],
]);

async function runTests(tests) {
  try {
    for (let [input, ast, html] of tests) {
      await runTest(input, ast, html);
    }
  } catch (error) {
    if (error.code === 'ERR_ASSERTION') {
      process.stderr.write('\n' + error.message + '\n');
      if (!error.expected) {
        process.stderr.write('\nNo recorded output found to compare to.\n\n');
      } else {
        const jestDiff = require('jest-diff');
        process.stderr.write(
          jestDiff(error.actual, error.expected, { expand: false })
        );
      }
    } else {
      process.stderr.write(error);
    }
  }
}

function runTest(input, ast, html) {
  const start = Date.now();
  process.stdout.write(`testing: ${input} ... `);
  return specMarkdown.parse(path.resolve(__dirname, input)).then(actualAST => {
    // Read expected snapshot files.
    let expectedAST;
    let expectedHTML;
    try {
      expectedAST = JSON.parse(
        fs.readFileSync(path.resolve(__dirname, ast), 'utf8')
      );
      expectedHTML = fs.readFileSync(path.resolve(__dirname, html), 'utf8');
    } catch (error) {
      if (error.code !== 'ENOENT') {
        throw error;
      }
    }

    try {
      assert.deepEqual(
        actualAST,
        expectedAST,
        'Did not parse expected AST.\n\n' +
          'If confident the changes are correct, rerun with RECORD set:\n' +
          '  $ RECORD=1 yarn test'
      );
    } catch (error) {
      if (shouldRecord) {
        fs.writeFileSync(
          path.resolve(__dirname, ast),
          JSON.stringify(actualAST, null, 2)
        );
      } else {
        throw error;
      }
    }

    // Print HTML after testing AST since it memoizes values in the AST.
    const actualHTML = specMarkdown.print(actualAST);
    try {
      assert.equal(
        actualHTML,
        expectedHTML,
        'Did not print expected HTML.\n\n' +
          'If confident the changes are correct, rerun with RECORD set:\n' +
          '  $ RECORD=1 yarn test'
      );
    } catch (error) {
      if (shouldRecord) {
        fs.writeFileSync(
          path.resolve(__dirname, ast),
          JSON.stringify(actualAST, null, 2)
        );
        if (actualHTML) {
          fs.writeFileSync(path.resolve(__dirname, html), actualHTML);
        }
      } else {
        throw error;
      }
    }

    process.stdout.write(`DONE (${Date.now() - start}ms) \n`);
  });
}

@@ -910,21 +910,62 @@
 r.write(
-error
+'%5Cn%5Cn' + String(error && error.stack %7C%7C error)
 );%0A    %7D
@@ -1171,88 +1171,8 @@
 %3E %7B%0A
-    // Read expected snapshot files.%0A    let expectedAST;%0A    let expectedHTML;%0A
     
@@ -1179,24 +1179,30 @@
 try %7B%0A      
+const 
 expectedAST 
@@ -1290,190 +1290,8 @@
  );%0A
-      expectedHTML = fs.readFileSync(path.resolve(__dirname, html), 'utf8');%0A    %7D catch (error) %7B%0A      if (error.code !== 'ENOENT') %7B%0A        throw error;%0A      %7D%0A    %7D%0A%0A    try %7B%0A
     
@@ -1539,32 +1539,66 @@
 or) %7B%0A      if (
+error.code === 'ERR_ASSERTION' && 
 shouldRecord) %7B%0A
@@ -1903,24 +1903,107 @@
 ;%0A    try %7B%0A
+      const expectedHTML = fs.readFileSync(path.resolve(__dirname, html), 'utf8');%0A
       assert
@@ -2254,174 +2254,58 @@
 if (
-shouldRecord) %7B%0A        fs.writeFileSync(%0A          path.resolve(__dirname, ast),%0A          JSON.stringify(actualAST, null, 2)%0A        );%0A        if (actualHTML
+error.code === 'ERR_ASSERTION' && shouldRecord
 ) %7B%0A
-  
     
@@ -2373,18 +2373,8 @@
 L);%0A
-        %7D%0A
     

Clean up test runner in record mode