(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('substance-test'), require('substance'), require('substance-pages')) :
	typeof define === 'function' && define.amd ? define(['substance-test', 'substance', 'substance-pages'], factory) :
	(factory(global.window.substanceTest,global.window.substance,global.window.substancePages));
}(this, (function (substanceTest,substance,substancePages) { 'use strict';

/*
 ATTENTION: this is an unsafe VM implementation.
 Don't use this with untrusted code.
*/
class Script {

  constructor(code) {
    this.code = `return (${code})`;
  }

  runInNewContext(ctx) {
    let symbols = Object.keys(ctx);
    let ExprFunction = Function.prototype.bind.apply(Function, [null].concat(symbols).concat(this.code));
    let f = new ExprFunction();
    let args = symbols.map((name) => {
      return ctx[name];
    });
    return f.apply(null, args);
  }

}



var stubVm = Object.freeze({
	Script: Script
});

substanceTest.test("replaceScriptlets: content scriptlet", (t) => {
  const html = "<div foo={{props.foo}}>{{props.children}}</div>";
  let { text, scriptlets } = substancePages.replaceScriptlets(html);
  t.equal(scriptlets.length, 2, "there should be two scriptlets");
  t.equal(text, "<div foo=@0@>@1@</div>", "scriptlets should have been replace correctly");
  t.equal(scriptlets[0], 'props.foo', "first scriptlet should be extracted correctly");
  t.equal(scriptlets[1], 'props.children', "second scriptlet should be extracted correctly");
  t.end();
});

substanceTest.test("HTMLTemplate: deriving actions", (t) => {
  const html = `
    <Foo src={{props.src}}>
      {{props.children}}
    </Foo>
  `;
  let template = new substancePages.HTMLTemplate(html, {
    // ATTENTION: tagNames get lower cased in HTML
    // so we need to register components correctly
    'foo': null
  });
  let actions = template.actions;
  t.equal(actions.length, 3, "there should be three actions");
  t.deepEqual(actions.map(a => a.type), ['fragment', 'attribute', 'component'], "the actions should be correctly identified");
  t.equal(actions[0].code, 'props.children', "first action should have correct code");
  t.equal(actions[1].name, 'src', "second action should be bound to 'src' attribute");
  t.equal(actions[1].code, 'props.src', ".. and should have correct code");
  t.equal(actions[2].name, 'foo', "third should have correct component name");
  t.end();
});

substanceTest.test("HTMLTemplate: expanding a template", (t) => {
  const input = `
    <Foo foo="bar">
      <p>Hello World</p>
    </Foo>
  `;
  let template = new substancePages.HTMLTemplate(input, {
    'foo': Foo
  });
  let { html } = template.expand(stubVm, { src: 'foo' });
  let dom = substance.DefaultDOMElement.parseHTML(html);
  let foo = dom.find('.foo');
  let baz = dom.find('.baz');
  let p = dom.find('p');
  t.notNil(foo, 'generated html should have element .foo');
  t.equal(foo.attr('foo'), 'bar', '.. with the provided attribute set correctly');
  t.notNil(baz, '.. and an element .baz');
  t.notNil(p, '.. and a paragraph');
  t.equal(p.text(), 'Hello World', '.... with correct content');
  t.end();
});

substanceTest.test("HTMLTemplate: scriptlet in same line", (t) => {
  const input = `
    <div>{{props.title}}</div>
  `;
  let template = new substancePages.HTMLTemplate(input);
  let { html } = template.expand(stubVm, { title: 'foo' });
  let dom = substance.DefaultDOMElement.parseHTML(html);
  let div = dom.find('div');
  t.notNil(div, 'generated html should have a <div> element');
  t.equal(div.text(), 'foo', '.. with correct content');
  t.end();
});

substanceTest.test("HTMLTemplate: expanding nested components", (t) => {
  const input = `
    <Foo>
      <Bar>Hello World</Bar>
    </Foo>
  `;
  let template = new substancePages.HTMLTemplate(input, {
    'foo': Foo,
    'bar': Bar
  });
  let { html } = template.expand(stubVm);
  let dom = substance.DefaultDOMElement.parseHTML(html);
  let foo = dom.find('.foo');
  let bar = dom.find('.bar');
  t.notNil(foo, 'generated html should have element .foo');
  t.notNil(bar, '.. and an element .bar');
  t.equal(bar.text(), 'Hello World', '.... with correct content');
  t.end();
});

substanceTest.test("HTMLTemplate: partial", (t) => {
  const foo = `
    <div class={{props.class}}>
      {{props.children}}
    </div>
  `;
  const input = `
    <Partial src='foo' class='bar'>
      <p>Hello World</p>
    </Partial>
  `;
  let templates = {};
  let components = {};

  templates['foo'] = new substancePages.HTMLTemplate(foo, components, templates);
  templates['bar'] = new substancePages.HTMLTemplate(input, components, templates);

  let template = templates['bar'];
  let { html } = template.expand(stubVm);
  let dom = substance.DefaultDOMElement.parseHTML(html);
  let bar = dom.find('.bar');
  let p = bar.find('p');
  t.notNil(bar, 'generated html should have element .bar');
  t.equal(p.text(), 'Hello World', '.. with a Hello World paragraph');
  t.end();
});

substanceTest.test("HTMLTemplate: nested partials", (t) => {
  const input = `
    <Partial src='foo'>
      <p>Hello World</p>
    </Partial>
  `;
  const FOO = `
    <div class='foo'>
      <Partial src='bar'>
        {{props.children}}
      </Partial>
    </div>
  `;
  const BAR = `
    <div class='bar'>
      {{props.children}}
    </div>
  `;

  let templates = {};
  let components = {};

  templates['foo'] = new substancePages.HTMLTemplate(FOO, components, templates);
  templates['bar'] = new substancePages.HTMLTemplate(BAR, components, templates);
  let template = new substancePages.HTMLTemplate(input, components, templates);

  let { html } = template.expand(stubVm);
  let dom = substance.DefaultDOMElement.parseHTML(html);
  let foo = dom.find('.foo');
  let bar = foo.find('.bar');
  let p = bar.find('p');
  t.notNil(foo, 'generated html should have element .foo');
  t.notNil(bar, '.. with child element .bar');
  t.equal(p.text(), 'Hello World', '.... containing a Hello World paragraph');
  t.end();
});

substanceTest.test("HTMLTemplate: self-closing partial", (t) => {
  const input = `
    <Partial src='foo' />
    <p>Hello World</p>
  `;
  const FOO = `
    <div class='foo'>YAY</div>
  `;
  let templates = {};
  let components = {};

  templates['foo'] = new substancePages.HTMLTemplate(FOO, components, templates);
  let template = new substancePages.HTMLTemplate(input, components, templates);

  let { html } = template.expand(stubVm);
  let dom = substance.DefaultDOMElement.parseHTML(html);
  let foo = dom.find('.foo');
  let p = dom.find('p');
  t.notNil(foo, 'generated html should have element .foo');
  t.equal(p.text(), 'Hello World', '.. and a Hello World paragraph');
  t.end();
});


class Foo extends substance.Component {
  render($$) {
    return $$('div').addClass('foo')
      .attr('foo', this.props.foo)
      .append(
        $$('div').addClass('baz')
          .append(this.props.children)
      )
  }
}

class Bar extends substance.Component {
  render($$) {
    return $$('div').addClass('bar')
      .append(this.props.children)
  }
}

})));

//# sourceMappingURL=./tests.js.map