{"version":3,"sources":["https://lively-kernel.org/lively4/lively4-stable/src/components/tools/lively-testrunner.js"],"names":["cop","Morph","isTestFile","fileName","match","TestRunner","testDir","get","setTestPath","path","value","initialize","windowTitle","registerButtons","addEventListener","event","keyCode","onRunButton","stopPropagation","preventDefault","querySelector","mochadiv","document","createElement","id","appendChild","innerHTML","lively","loadCSSThroughDOM","lively4url","resetMocha","getAttribute","e","testDirChanged","findTestFilesInDir","dir","files","walkDir","console","error","filter","findTestFiles","dirs","file","startsWith","substring","URL","href","infoString","statFile","type","JSON","parse","list","split","log","newFiles","concat","clearTests","mocha","suite","tests","length","suites","loadTestsInOrder","testFiles","url","name","replace","reloadModule","System","import","loadTests","Promise","all","map","textContent","runTests","self","run","failures","prevState","isRunning","window","history","pushState","prevLocation","undefined","fixHTML","onResetButton","loadJavaScriptThroughDOM","then","setup","querySelectorAll","forEach","ea","onclick","evt","state","location","toString","grep","mochastate","onTestDirChanged","runMocha","resolve","reject","compact","pluck","loadedTests","include","flatten","Error","join","reporter","Reporter","runner","on","test","t","detect","fullTitle","update","showError","stack","duration","attachErrorToTest","parentTests","parent","invoke","livelyMigrate","other","livelyPrepareSave","setAttribute"],"mappings":"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","file":"lively-testrunner.js","sourcesContent":["import * as cop from \"src/client/ContextJS/src/contextjs.js\"\nimport Morph from 'src/components/widgets/lively-morph.js';\n\n\n/*MD # Testrunner \n\n[doc](browse://doc/tools/test-runner.md)\n\n![](../../../doc/tools/media/test-runner.png){width=400px}\n\nMD*/\n\n//     Mocha.utils.parseQuery()\n\n// var parseQueryLayer = cop.create(\"MochaParseQueryLayer\");\n// parseQueryLayer.layerObject(Mocha.utils, {\n\n// });\n\nexport function isTestFile(fileName) {\n  return fileName.match(/(-|\\.)(spec|test)\\.js$/);\n}\n\nexport default class TestRunner extends Morph {\n  get testDir() { return this.get('#testDir'); }\n  setTestPath(path) {\n    this.testDir.value = path;\n  }\n\n  initialize() {\n    \n    this.windowTitle = \"Test Runner\"\n    this.registerButtons();\n    // lively.html.registerInputs(this)\n    this.testDir.addEventListener('keydown', event => {\n      if (event.keyCode == 13) { // ENTER\n        this.onRunButton();\n        event.stopPropagation();\n        event.preventDefault();\n      }\n    });\n\n    if (!this.querySelector(\"#mocha\")) {\n      this.mochadiv = document.createElement(\"div\");\n      this.mochadiv.id = \"mocha\";\n      this.appendChild(this.mochadiv);\n    } else {\n      this.mochadiv = this.querySelector(\"#mocha\");\n    }\n    this.querySelector(\"#mocha\").innerHTML = \"\";\n\n    lively.loadCSSThroughDOM(\"mochaCSS\", lively4url + \"/src/external/mocha.css\");\n\n    this.resetMocha();\n\n    var testDir =  this.getAttribute('testDir');\n    if (testDir) {\n      this.testDir.value = testDir;\n    }\n    this.testDir.addEventListener(\"input\", e => this.testDirChanged(e));\n  }\n\n  async findTestFilesInDir(dir) {\n    try {\n      var files = await lively.files.walkDir(lively4url + dir);\n    } catch(e) {\n      console.error(e)\n      files = []\n    }\n    return files.filter(isTestFile);\n  }\n\n  async findTestFiles() {\n    const dirs = this.testDir.value;\n    \n    // single file?\n    if (isTestFile(dirs)) {\n      try {\n        var file = dirs.startsWith('/') ? dirs.substring(1) : dirs;\n        file = new URL(file, lively4url+'/').href\n        const infoString = await lively.files.statFile(file);\n        const { type } = JSON.parse(infoString);\n        if (type === 'file') {\n          return [file];\n        }\n      } catch(e) {}\n    }\n\n    var files = []\n    var list = dirs.split(\",\")\n    console.log(\"[testrunner] findTestFiles: \" + list)\n\n    // await Promise.all(list.map((dir) => {\n    //   console.log(\"find test file in dir: \" + dir)\n    //   return this.findTestFilesInDir(dir).then(newFiles => {\n    //     files = files.concat(newFiles)\n    //   })\n    // }));\n\n    for (let dir of list) {\n      let newFiles = await this.findTestFilesInDir(dir)\n      files = files.concat(newFiles)\n    }\n\n    return files\n    // #WhyNotThis\n    // return [\"/test/\", \"/test/templates/\"].reduce(async (sum, ea) => {\n    //     return sum.concat(await this.findTestFilesInDir(ea))\n    // }, [])\n  }\n  // await that.findTestFilesInDir( \"/test/templates/\")\n\n  clearTests() {\n    if (mocha.suite) {\n      mocha.suite.tests.length = 0; \n      mocha.suite.suites.length = 0; \n    }\n    this.querySelector(\"#mocha\").innerHTML= \"\";\n  }\n\n  async loadTestsInOrder() {\n    \n    var testFiles = await this.findTestFiles()\n    for(var url of testFiles) {\n      var name = url.replace(/.*\\//,\"\").replace(/\\/\\.[^\\.]*/,\"\");\n      // lively.notify(\"loadTest: \" + name)\n      await lively.reloadModule(url);\n      await System.import(url);\n    }\n  }\n\n  \n  async loadTests() {\n    var testFiles = await this.findTestFiles()\n    return Promise.all(testFiles.map(async url => {\n      var name = url.replace(/.*\\//,\"\").replace(/\\/\\.[^\\.]*/,\"\");\n      await lively.reloadModule(url);\n      await System.import(url);\n      this.get(\"#log\").textContent += \"loaded Test: \" + name + \"\\n\"\n    }))\n  }\n\n  runTests() {\n    this.get(\"#log\").textContent = \"\"\n    var self = this;\n    mocha.run(failures => {\n      if (self.prevState) {\n        this.isRunning = false\n        window.history.pushState(self.prevState, '', self.prevLocation + \"&grep=.*\");\n        self.prevState = self.prevLocation = undefined;\n      }\n      self.fixHTML();\n    });\n  }\n\n  async onRunButton() {\n    this.clearTests();\n    \n    await this.loadTests();\n    this.runTests();\n  }\n\n  async onResetButton() {\n    this.clearTests();\n    this.resetMocha();\n  }\n\n  // some tests, e.g. ContextJS manage to break mocha, so that they can be only once... without this\n  resetMocha() {\n    return lively.loadJavaScriptThroughDOM(\"mochaJS\", lively4url + \"/src/external/mocha.js\", true).then(() => {\n      mocha.setup(\"bdd\");\n    });\n  }\n\n  //  window.history.pushState({ mochastate: true }, '',        window.location);\n  fixHTML() {\n    var self = this;\n    this.mochadiv.querySelectorAll(\".replay\").forEach(ea => {\n      ea.innerHTML = \"R\";\n      ea.onclick = (evt) => {\n        evt.preventDefault();\n        self.prevState = window.history.state;\n        self.prevLocation = window.location.toString().replace(/&grep=[^&]+/, '');\n        var grep = ea.href.replace(/.*(&grep.*)/, '$1');\n        window.history.pushState({ mochastate: true }, '', self.prevLocation + grep);\n        self.onRunButton();\n        return false;\n      };\n    });\n  }\n\n  async onTestDirChanged() {\n    this.onRunButton()\n  }\n\n  runMocha() {\n    // #TODO port this to Lively4\n  var self = this;\n\n// this.runTestFile(\"http://localhost:9001/lively-mocha-tester/tests/test-test.js\")\n\n  return new Promise((resolve, reject) => {\n      var files = mocha.suite.suites.compact().pluck(\"file\")\n      var tests = this.state.loadedTests.filter(ea => files.include(ea.file)).pluck(\"tests\").flatten();\n\n      if (!tests || !tests.length)\n        return reject(new Error(`Trying to run tests of ${files.join(\", \")} but cannot find them in loaded tests!`));\n\n      mocha.reporter(function Reporter(runner) {\n        // this.done = (failures) => show(\"done \" + failures)\n        // runner.on(\"suite\", function (x) { show(\"suite %s\", x) });\n        // runner.on(\"pending\", function (x) { show(\"pending %s\", x) });\n\n        runner.on(\"test\", test => {\n          try {\n            var t = tests.detect(ea => ea.fullTitle === test.fullTitle());\n            t.state = \"running\";\n            self.update();\n          } catch (e) { self.showError(\"runner on test error: \" + e.stack); }\n        });\n\n        // runner.on(\"test end\", test => {\n        //   try {\n        //     var t = tests.tests.detect(ea => ea.fullTitle === test.fullTitle();\n        //     t.state = \"finished\";\n        // self.update();\n        //   } catch (e) { self.showError(\"error: \" + e.stack); }\n        // });\n\n        runner.on(\"pass\", test => {\n          try {\n            var t = tests.detect(ea => ea.fullTitle === test.fullTitle());\n            t.state = \"succeeded\";\n            t.duration = test.duration;\n            self.update();\n          } catch (e) { self.showError(\"runner on pass error: \" + e.stack); }\n        });\n\n        runner.on(\"fail\", (test, error) => {\n          try {\n            var t = tests.detect(ea => ea.fullTitle === test.fullTitle());\n            if (t) attachErrorToTest(t, error, test.duration);\n            else { // \"test\" is a hook...\n              var parentTests = test.parent.tests.invoke(\"fullTitle\")\n              tests\n                .filter(ea => parentTests.include(ea.fullTitle))\n                .forEach(ea => attachErrorToTest(ea, error, test.duration))\n            }\n\n            self.update();\n\n            function attachErrorToTest(test, error, duration) {\n              test.state = \"failed\";\n              test.duration = test.duration;\n              test.error = error;\n            }\n\n          } catch (e) { self.showError(\"runner on fail error: \" + e.stack); }\n        });\n\n        // runner.on(\"start\", test => { show(\"START %o\", lively.printInspect(test ,1)) });\n        // runner.on(\"end\", test => { show(\"end %o\", lively.printInspect(test ,1)) });\n\n        // runner.on(\"hook end\", function (x) { show(\"hook end %s\", x) });\n        // runner.on(\"suite end\", function (x) { show(\"suite end %s\", x) });\n      });\n\n      mocha.run(failures => resolve());\n    });\n  }\n\n  livelyMigrate(other) {\n    this.testDir.value = other.testDir.value;\n  }\n\n  livelyPrepareSave() {\n    this.setAttribute('testDir', this.testDir.value);\n  }\n\n  testDirChanged(e) {\n    this.setAttribute('testDir', this.testDir.value);\n  }\n}\n"]}