diff --git a/.travis.yml b/.travis.yml index 6e569da..2c096f9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,4 +7,4 @@ before_install: - docker build -t funcpack-test-suite . script: - - docker run -e "DEBUG=azure-functions-pack:*" funcpack-test-suite:latest \ No newline at end of file + - docker run -e "DEBUG=azure-functions-pack:*" -e "DEBUG_FD=1" funcpack-test-suite:latest \ No newline at end of file diff --git a/src/utils/fs-helper.ts b/src/utils/fs-helper.ts index 5c74d18..314a4ca 100644 --- a/src/utils/fs-helper.ts +++ b/src/utils/fs-helper.ts @@ -75,11 +75,25 @@ export class FileHelper { public static writeFileUtf8(path: string, content: string): Promise { return new Promise((resolve, reject) => { + // after generating the file forward date the modified TimeStamp + // This gets around webpack watcher back dating its directory file watcher. + // Without this the watcher was executing continously for + // DirectoryWatcher.FS_ACCURACY / WatchOptions.aggregateTimeout times fs.writeFile(path, content, (err) => { if (err) { return reject(err); } - resolve(); + fs.stat(path, (err1, stats) => { + if (err1) { + return reject(err); + } + fs.utimes(path, stats.atime, new Date(stats.mtime.getMilliseconds() + 10000), (err2) => { + if (err2) { + return reject(err); + } + resolve(); + }); + }); }); }); } diff --git a/src/webpack-runner.ts b/src/webpack-runner.ts index a1d5c8c..ac13551 100644 --- a/src/webpack-runner.ts +++ b/src/webpack-runner.ts @@ -83,11 +83,12 @@ export class WebpackRunner { debug("Started webpack"); if (options.watch) { - compiler.watch(null, async (err, stats) => { + compiler.watch(null, (err, stats) => { debug("Webpack recompile"); if (err || stats.hasErrors()) { return reject(err || stats.toString({ errors: true })); } + winston.info("Webpack compiled successfully. Watching for changes."); debug("\n" + stats.toString()); }); } else { diff --git a/test/e2e/e2e.test.ts b/test/e2e/e2e.test.ts index 3bd40f8..5b07fdd 100644 --- a/test/e2e/e2e.test.ts +++ b/test/e2e/e2e.test.ts @@ -248,6 +248,153 @@ describe("e2e tests", function() { .expect(200, done); }); + it("should work with simple imports", function(done) { + host.test("simpleimport") + .expect(200, done); + }); + }); + }); + + describe("funcpack pack -w . ", function() { + const randomNumber = Math.floor(Math.random() * 10000); + const testRoot = path.resolve(os.tmpdir(), `./AzureFunctionsPackTest${randomNumber}`); + log(`Using temp dir: ${testRoot}`); + describe("cli", function() { + before(async function() { + this.timeout(60000); + return await FileHelper.cp(sampleRoot, testRoot); + }); + + after(async function() { + this.timeout(60000); + if (process.env.FUNCPACK_TESTS_CLEAN) { + return await FileHelper.rimraf(testRoot); + } else { + return Promise.resolve(); + } + }); + + it("should run successfully", async function() { + this.timeout(60000); + try { + const childProcess = spawn("node", + [path.resolve(__dirname, "../../lib/main.js"), "pack", "-w", "."], { cwd: testRoot }); + + const waitForWatch = await new Promise((resolve, reject) => { + childProcess.stdout.on("data", (data: string) => { + if (data.toString().includes ("Webpack compiled successfully. Watching for changes.")) { + resolve(true); + childProcess.kill(); + } + }); + + childProcess.stderr.on("data", (data: string) => { + reject(data.toString()); + childProcess.kill(); + }); + }); + + return Promise.resolve(); + } catch (e) { + return Promise.reject(e); + } + }); + }); + + describe("host", function() { + let host: FunctionHostHarness; + + before(async function() { + this.timeout(90000); + await ProcessHelper.killAllFunctionsHosts(); + if (!await FileHelper.exists(testRoot)) { + await FileHelper.cp(sampleRoot, testRoot); + } + const childProcess = spawn("node", + [path.resolve(__dirname, "../../lib/main.js"), "pack", "-w", "."], { cwd: testRoot }); + + const waitForWatch = await new Promise((resolve, reject) => { + childProcess.stdout.on("data", (data: string) => { + if (data.toString().includes ("Webpack compiled successfully. Watching for changes.")) { + resolve(true); + childProcess.kill(); + } + }); + + childProcess.stderr.on("data", (data: string) => { + reject(data.toString()); + childProcess.kill(); + }); + }); + + host = new FunctionHostHarness(testRoot); + await host.init(); + return new Promise((resolve, reject) => { + const int = setInterval(() => { + host.test("simple") + .then((res: any) => { + log(JSON.stringify(res)); + if (res.status === 200) { + clearTimeout(int); + resolve(); + } + }).catch((e) => log(e)); + }, 500); + }); + }); + + after(async function() { + this.timeout(60000); + host.stop(); + await ProcessHelper.killAllFunctionsHosts(); + if (process.env.FUNCPACK_TESTS_CLEAN) { + return await FileHelper.rimraf(testRoot); + } else { + return Promise.resolve(); + } + }); + + it("should ignore non-js files", function(done) { + const funcname = process.env.FUNCPACK_TESTS_V2 ? "cs-ignoreme-v2" : "cs-ignoreme"; + host.test(funcname) + .expect(200, done); + }); + + it("should obey entryPoint setting", function(done) { + host.test("entryPoint") + .expect(200, done); + }); + + it("should obey excluded setting", function(done) { + host.test("excluded") + .expect(200, done); + }); + + it("should work with external script files", function(done) { + host.test("externalScriptFile") + .expect(200, done); + }); + + it("should work with large imports", function(done) { + host.test("largeimport") + .expect(200, done); + }); + + it("should work with local libs", function(done) { + host.test("libimport") + .expect(200, done); + }); + + it("should obey scriptFile setting", function(done) { + host.test("scriptFile") + .expect(200, done); + }); + + it("should work with simple functions", function(done) { + host.test("simple") + .expect(200, done); + }); + it("should work with simple imports", function(done) { host.test("simpleimport") .expect(200, done); @@ -255,4 +402,5 @@ describe("e2e tests", function() { }); }); + });