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

const path = require('path');
const readFileSync = require('fs').readFileSync;
const {getTOC, insertTOC} = require('../toc');
const {extractMetadata} = require('../../server/metadataUtils');

const getTOCmd = readFileSync(
  path.join(__dirname, '__fixtures__', 'getTOC.md'),
  'utf8',
);

const insertTOCmd = readFileSync(
  path.join(__dirname, '__fixtures__', 'insertTOC.md'),
  'utf8',
);

describe('getTOC', () => {
  test('with defaults', () => {
    const headings = getTOC(getTOCmd);
    const headingsJson = JSON.stringify(headings);

    expect(headings).toMatchSnapshot();
    expect(headingsJson).toContain('bar-8'); // maximum unique bar index is 8
    expect(headingsJson).not.toContain('4th level headings');
  });

  test('with custom heading levels', () => {
    const headings = getTOC(getTOCmd, 'h2', ['h3', 'h4']);
    const headingsJson = JSON.stringify(headings);

    expect(headings).toMatchSnapshot();
    expect(headingsJson).toContain('bar-8'); // maximum unique bar index is 8
    expect(headingsJson).toContain('4th level headings');
  });

  test('html tag in source', () => {
    const headings = getTOC(`## <a name="foo"></a> Foo`, 'h2', []);

    expect(headings[0].hashLink).toEqual('a-namefooa-foo');
    expect(headings[0].rawContent).toEqual(`<a name="foo"></a> Foo`);
    expect(headings[0].content).toEqual(`<a name="foo"></a> Foo`);
  });

  test('transform markdown syntax to html syntax', () => {
    const headings = getTOC(`## <a name="foo"></a> _Foo_`, 'h2', []);

    expect(headings[0].hashLink).toEqual('a-namefooa-_foo_');
    expect(headings[0].rawContent).toEqual(`<a name="foo"></a> _Foo_`);
    expect(headings[0].content).toEqual(`<a name="foo"></a> <em>Foo</em>`);

    const headings2 = getTOC(`## **Foo**`, 'h2', []);

    expect(headings2[0].hashLink).toEqual('foo');
    expect(headings2[0].rawContent).toEqual(`**Foo**`);
    expect(headings2[0].content).toEqual(`<strong>Foo</strong>`);
  });

  test('does not strip tags randomly', () => {
    // eslint-disable-next-line no-useless-escape
    const headings = getTOC(`## function1 [array\<string>]`, 'h2', []);

    expect(headings[0].hashLink).toEqual('function1-arraystring');
    expect(headings[0].rawContent).toEqual(`function1 [array<string>]`);
    expect(headings[0].content).toEqual(`function1 [array<string>]`);
  });

  test('test slugPreprocessor', () => {
    const headings = getTOC(`## <a name="foo"></a> Foo`, 'h2', [], (s) =>
      s.replace(/foo/gi, 'bar'),
    );

    expect(headings[0].hashLink).toEqual('a-namebara-bar');
    expect(headings[0].rawContent).toEqual(`<a name="foo"></a> Foo`);
    expect(headings[0].content).toEqual(`<a name="foo"></a> Foo`);
  });
});

describe('insertTOC', () => {
  test('null or undefined content', () => {
    expect(insertTOC(null)).toBeNull();
    expect(insertTOC(undefined)).toBeUndefined();
  });

  test('AUTOGENERATED_TABLE_OF_CONTENTS does not exist', () => {
    const rawContent = extractMetadata(getTOCmd).rawContent;
    expect(insertTOC(rawContent)).toMatchSnapshot();
    expect(insertTOC(rawContent)).toEqual(rawContent);
  });

  test('AUTOGENERATED_TABLE_OF_CONTENTS exists', () => {
    const rawContent = extractMetadata(insertTOCmd).rawContent;
    expect(insertTOC(rawContent)).toMatchSnapshot();
    expect(insertTOC(rawContent)).not.toEqual(rawContent);
  });
});
