#!/usr/bin/env node

'use strict';

/**
 * Validate that a given component can actually server-side render
 * with the given properties (specified via a fixture file).
 *
 * Not all react components can be server-side rendered: they may
 * use globals, or access the DOM, or what hafve you.  This script
 * can be used to validate that the component *can* be server-side
 * rendered.
 *
 * The input is a bit difficult to construct: it's a json list of
 * objects like so:
 *    {
 *      jsPackages: [[pkg_name, pkg_contents], [pkg_name, pkg_contents], ...],
 *      pathToReactComponent: "./in/require/format.js",
 *      fixtureFile: "/ideally/an/absolute/path",
 *    }
 *
 * We require() the fixture file and try to server-side render the
 * component using each fixture found therein.  jsPackages are the
 * packages needed to render the component (including the package
 * that defines the component!) topologically sorted so no package
 * require()s anything from a package that comes after it.
 */

/* eslint-disable no-console */

const path = require("path");

const render = require("../src/render.js");


// Returns the number of errors found trying to render the component.
const validate = function(jsPackages, pathToReactComponent, fixtureFile) {
    let allProps;
    try {
        const relativeFixturePath = path.relative(__dirname, fixtureFile);
        allProps = require(relativeFixturePath).instances;
    } catch (err) {
        console.log(`Error reading fixtures from ${fixtureFile}: ${err}`);
        return 1;
    }

    let numErrors = 0;
    allProps.forEach((props, i) => {
        try {
            render(jsPackages, pathToReactComponent, props, 'ignore');
            console.log(`${pathToReactComponent} #${i}: OK`);
        } catch (err) {
            console.log(`${pathToReactComponent} #${i}: ERROR: ${err}`);
            numErrors++;
        }
    });
    return numErrors;
};


const main = function(inputJson) {
    let numErrors = 0;
    inputJson.forEach((oneInput) => {
        numErrors += validate(oneInput.jsPackages,
                              oneInput.pathToReactComponent,
                              oneInput.fixtureFile);
    });
    return numErrors;
};


let inputText = '';
process.stdin.on('data', function(chunk) {
    inputText = inputText + chunk;
});
process.stdin.on('end', function() {
    const inputJson = JSON.parse(inputText);
    const numErrors = main(inputJson);
    console.log('DONE');
    process.exit(numErrors);
});

Add a simple script to validate that a component can be server-side rendered.
Add a simple script to validate that a component can be server-side rendered.

This is intended for use with webapp's
react_util/server_side_render_test.py.

Auditors: jlfwong

Test Plan:
In webapp, ran
   tools/runtests.py --max-size=large react_util/server_side_render_test.py
It completed successfully.

I then changed the cache policy in validate_components.js from
'ignore' to 'yes', and ran the test again, and saw it fail as so:

    AssertionError: ./javascript/page-package/stateful-header.jsx #0: ERROR: TypeError: Cannot read property 'get' of undefined
    ./javascript/content-library-package/curation-page.jsx #0: ERROR: TypeError: Cannot read property 'get' of undefined
    ./javascript/content-library-package/curation-page.jsx #1: ERROR: TypeError: Cannot read property 'get' of undefined
    ./javascript/content-library-package/curation-page.jsx #2: ERROR: TypeError: Cannot read property 'get' of undefined
    ./javascript/content-library-package/curation-page.jsx #3: ERROR: TypeError: Cannot read property 'get' of undefined
    ./javascript/style-package/style-guide.jsx #0: ERROR: TypeError: Cannot read property 'get' of undefined
    ./javascript/about-package/alumni.jsx #0: ERROR: TypeError: Cannot read property 'get' of undefined

This shows that it is properly iterating over all the relevant
components and all their relevant fixtures.  (The 'get' error is
because I never initialize the cache, so trying to use the cache
fails.)
