/**
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import * as t from '@babel/types';
import invariant from 'invariant';
import {runBabelPluginReactCompiler} from '../Babel/RunReactCompilerBabelPlugin';
import type {Logger, LoggerEvent} from '../Entrypoint';

it('logs succesful compilation', () => {
  const logs: [string | null, LoggerEvent][] = [];
  const logger: Logger = {
    logEvent(filename, event) {
      logs.push([filename, event]);
    },
  };

  const _ = runBabelPluginReactCompiler(
    'function Component(props) { return <div>{props}</div> }',
    'test.js',
    'flow',
    {logger, panicThreshold: 'all_errors'},
  );

  const [filename, event] = logs.at(0)!;
  expect(filename).toContain('test.js');
  expect(event.kind).toEqual('CompileSuccess');
  invariant(event.kind === 'CompileSuccess', 'typescript be smarter');
  expect(event.fnName).toEqual('Component');
  expect(event.fnLoc?.end).toEqual({column: 55, index: 55, line: 1});
  expect(event.fnLoc?.start).toEqual({column: 0, index: 0, line: 1});
});

it('logs failed compilation', () => {
  const logs: [string | null, LoggerEvent][] = [];
  const logger: Logger = {
    logEvent(filename, event) {
      logs.push([filename, event]);
    },
  };

  expect(() => {
    runBabelPluginReactCompiler(
      'function Component(props) { props.foo = 1; return <div>{props}</div> }',
      'test.js',
      'flow',
      {logger, panicThreshold: 'all_errors'},
    );
  }).toThrow();

  const [filename, event] = logs.at(0)!;
  expect(filename).toContain('test.js');
  expect(event.kind).toEqual('CompileError');
  invariant(event.kind === 'CompileError', 'typescript be smarter');

  expect(event.detail.severity).toEqual('InvalidReact');
  //@ts-ignore
  const {start, end, identifierName} = event.detail.loc as t.SourceLocation;
  expect(start).toEqual({column: 28, index: 28, line: 1});
  expect(end).toEqual({column: 33, index: 33, line: 1});
  expect(identifierName).toEqual('props');

  // Make sure event.fnLoc is different from event.detail.loc
  expect(event.fnLoc?.start).toEqual({column: 0, index: 0, line: 1});
  expect(event.fnLoc?.end).toEqual({column: 70, index: 70, line: 1});
});