JSlang.dev

JavaScript Deep Dives with Wolfram. Since 2015
Inclusive, Test-Driven, Spec-Focused, Collaborative.

November 19, 2020
TestsSource
Tagged Templates

Source Code

The source code we wrote during the event.

import assert from 'assert';

describe('Tagged templates - what the function`s signature', () => {
  it('the number of arguments is 2 for one substitute', () => {
    let expectedArgs = undefined;
    const fn = (...args) => { expectedArgs = args; };
    const x = 1;
    fn`${x}`;
    assert.equal(expectedArgs.length, 2);
  });
  it('the first argument is an array with only the template string', () => {
    let expectedArgs = undefined;
    const fn = (...args) => { expectedArgs = args; };
    fn`template string`;
    assert.deepEqual(expectedArgs[0], ['template string']);
  });
  it('a tagged template without substitutes has only 1 argument', () => {
    let expectedArgs = undefined;
    const fn = (...args) => { expectedArgs = args; };
    fn`template string`;
    assert.strictEqual(expectedArgs.length, 1);
  });
  it('a substitute is NOT part of the first argument', () => {
    let expectedArgs = undefined;
    const fn = (...args) => { expectedArgs = args; };
    fn`template ${42} string`;
    assert.deepEqual(expectedArgs[0], ['template ', ' string']);
  });
  it('the first substitute is the second argument', () => {
    let expectedArgs = undefined;
    const fn = (...args) => { expectedArgs = args; };
    fn`template ${42} string`;
    assert.deepEqual(expectedArgs[1], 42);
  });
  it('the second substitute is the third argument', () => {
    let expectedArgs = undefined;
    const fn = (...args) => { expectedArgs = args; };
    fn`template ${42} string ${23}`;
    assert.deepEqual(expectedArgs[2], 23);
  });
  it('using a number as a tagged literal throws TypeError', () => {
    const number = 7;
    assert.throws(() => {
      number``
    }, TypeError);
  });
  it('using an array as a tagged literal throws TypeError', () => {
    const arr = [7];
    assert.throws(() => {
      arr``
    }, TypeError);
  });
  it('using an anonymous arrow fn as a tagged literal does not throw', () => {
    assert.doesNotThrow(() => {
      (()=>{})``
    });
  });
});

describe('What does it return?', () => {
  it('the return value of the tagged template is the return value of the function', () => {
    const x = {a: 42};
    const fn = () => x;
    const result = fn``;
    assert.strictEqual(result, x);
  });
  it('the return value of the tagged template is the not-mutated return value of the function', () => {
    const x = {a: 42};
    const fn = () => x;
    const result = fn``;
    assert.deepEqual(result, {a: 42});
  });
  it('four backticks trick', () => {
    const fn = () => () => 42;
    assert.strictEqual(fn````, 42);
  });
  it('"async somehow"', () => {
    const fn = async () => 42;
    assert(fn`` instanceof Promise);
  });
  it('when the function throws it throws', () => {
    const fn = () => { throw RangeError(); };
    assert.throws(() => { fn``; }, RangeError);
  });
});