/**
 * @jest-environment jsdom
 */

/*
 * Copyright (c) 2023 Eclipse Foundation, Inc.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * Contributors:
 *   Olivier Goulet <olivier.goulet@eclipse-foundation.org>
 *
 * SPDX-License-Identifier: EPL-2.0
 */

import renderTemplate from '../templates/render-template';
import templateWithPartial from './template-with-partial.mustache';

// Precompiled templates
const templates = {
  default: () => `<div>Default Template</div>`,
  alternative: () => `<div>Alternative Template</div>`,
  'data-template': text => `<div>${text}</div>`,
  'template-with-partial': templateWithPartial,
};

const partials = {
  cart: `
    <ul>
      {{#products}}
        <li>{{name}}\t{{amount}}</li>
      {{/products}}
    </ul>
  `
}

describe('renderTemplate', () => {
  afterEach(() => {
    document.querySelector('body').innerHTML = '';
  });

  it('Renders the specified template', async () => {
    const wrapperElement = document.createElement('div');

    // Expect the 'default' template to render inside the wrapper element
    let templateName = 'default';
    await renderTemplate({
      templates,
      templateId: templateName,
      element: wrapperElement,
    });
    expect(wrapperElement.innerHTML).toEqual(templates[templateName]());

    // Expect the 'alternative' template to render inside the wrapper element
    templateName = 'alternative';
    await renderTemplate({
      templates,
      templateId: templateName,
      element: wrapperElement,
    });
    expect(wrapperElement.innerHTML).toEqual(templates[templateName]());
  });

  it('Renders custom templates', async () => {
    const customTemplate = `<div>Custom Template</div>`;

    document.querySelector('body').innerHTML = `
            <script id="custom-template" type="x-tmpl-mustache">
                ${customTemplate}
            </script>
        `;

    const wrapperElement = document.createElement('div');

    // Expect the template defined in the #custom-template script to render inside the wrapper
    // element
    await renderTemplate({
      element: wrapperElement, 
      templates, 
      templateId: 'custom-template'
    });
    expect(wrapperElement.innerHTML.trim()).toEqual(customTemplate);
  });

  it('Renders data given to the template', async () => {
    const textData = 'This is some text data';
    const wrapperElement = document.createElement('div');

    await renderTemplate({
      templates, 
      templateId: 'data-template', 
      element: wrapperElement, 
      data: textData
    });
    expect(wrapperElement.innerHTML).toContain(textData);
  });

  it('Shows error message when template could not be found', async () => {
    const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
    const wrapperElement = document.createElement('div');

    await renderTemplate({
      templates, 
      templateId: 'undefined-template',
      element: wrapperElement, 
    });
    expect(wrapperElement.innerHTML).toBe('');

    expect(consoleSpy).toHaveBeenCalledWith(
        expect.stringContaining('has not been found')
    );

    consoleSpy.mockRestore();
  });

  it.skip('Renders a partial', async () => {
    const productsData = {
        products: [
          { amount: '$5.99', name: 'Orange Juice' },
          { amount: '$7.99', name: 'Maple Syrup' },
      ]
    };

    const wrapperElement = document.createElement('div');

    await renderTemplate({
      templates,
      templateId: 'template-with-partial',
      element: wrapperElement,
      data: {
        username: 'webdev',
        nearestStore: 'Ottawa, ON',
        ...productsData,
      },
      partials: {
        cart: partials.cart,
      }
    });

    expect(wrapperElement.innerHTML).toContain(productsData.products[0].name);
  });
});
