/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

// Tests for preview through Babel's compile output.
requestLongerTimeout(3);

async function breakpointPreviews(dbg, fixture, { line, column }, previews) {
  const filename = `fixtures/${fixture}/input.js`;
  const fnName = fixture.replace(/-([a-z])/g, (s, c) => c.toUpperCase());

  log(`Starting ${fixture} tests`);

  await invokeWithBreakpoint(dbg, fnName, filename, { line, column }, async () => {
    await assertPreviews(dbg, previews);
  });

  ok(true, `Ran tests for ${fixture} at line ${line} column ${column}`);
}

function testForOf(dbg) {
  return breakpointPreviews(dbg, "babel-for-of", { line: 5, column: 4 }, [
    {
      line: 5,
      column: 7,
      expression: "doThing",
      result: "doThing(arg)",
    },
    {
      line: 5,
      column: 13,
      expression: "x",
      result: "1",
    },
    {
      line: 8,
      column: 16,
      expression: "doThing",
      result: "doThing(arg)",
    },
  ]);
}

function testShadowing(dbg) {
  return breakpointPreviews(dbg, "babel-shadowed-vars", { line: 18, column: 6 }, [
      // These aren't what the user would expect, but we test them anyway since
      // they reflect what this actually returns. These shadowed bindings read
      // the binding closest to the current frame's scope even though their
      // actual value is different.
      {
        line: 2,
        column: 9,
        expression: "aVar",
        result: '"var3"',
      },
      {
        line: 3,
        column: 9,
        expression: "_aLet2;",
        result: '"let3"',
      },
      {
        line: 4,
        column: 11,
        expression: "_aConst2;",
        result: '"const3"',
      },
      {
        line: 10,
        column: 11,
        expression: "aVar",
        result: '"var3"',
      },
      {
        line: 11,
        column: 11,
        expression: "_aLet2;",
        result: '"let3"',
      },
      {
        line: 12,
        column: 13,
        expression: "_aConst2;",
        result: '"const3"',
      },

      // These actually result in the values the user would expect.
      {
        line: 14,
        column: 13,
        expression: "aVar",
        result: '"var3"',
      },
      {
        line: 15,
        column: 13,
        expression: "_aLet2;",
        result: '"let3"',
      },
      {
        line: 16,
        column: 13,
        expression: "_aConst2;",
        result: '"const3"',
      },
    ]);
}

function testImportedBindings(dbg) {
  return breakpointPreviews(dbg, "babel-modules-cjs", { line: 20, column: 2 }, [
   {
     line: 22,
     column: 16,
     expression: "_mod2.default;",
     result: '"a-default"',
   },
   {
     line: 23,
     column: 16,
     expression: "_mod4.original;",
     result: '"an-original"',
   },
   {
     line: 24,
     column: 16,
     expression: "_mod3.aNamed;",
     result: '"a-named"',
   },
   {
     line: 25,
     column: 16,
     expression: "_mod3.aNamed;",
     result: '"a-named"',
   },
   {
     line: 26,
     column: 16,
     expression: "aNamespace",
     fields: [
       ['aNamed', 'a-named'],
       ['default', 'a-default'],
     ],
   },
   {
     line: 31,
     column: 20,
     expression: "_mod7.default;",
     result: '"a-default2"',
   },
   {
     line: 32,
     column: 20,
     expression: "_mod9.original;",
     result: '"an-original2"',
   },
   {
     line: 33,
     column: 20,
     expression: "_mod8.aNamed2;",
     result: '"a-named2"',
   },
   {
     line: 34,
     column: 20,
     expression: "_mod8.aNamed2;",
     result: '"a-named2"',
   },
   {
     line: 35,
     column: 20,
     expression: "aNamespace2",
     fields: [
       ['aNamed', 'a-named2'],
       ['default', 'a-default2'],
     ],
   },
 ]);
}


add_task(async function() {
  await pushPref("devtools.debugger.features.map-scopes", true);
  const dbg = await initDebugger("doc-sourcemapped.html");

  await testForOf(dbg)
  await testShadowing(dbg)
  await testImportedBindings(dbg)
});
