UNPKG

hot-import

Version:

Hot Module Replacement (HMR) for Node.js

270 lines 13.1 kB
#!/usr/bin/env ts-node "use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; Object.defineProperty(exports, "__esModule", { value: true }); const path = require("path"); // tslint:disable:no-shadowed-variable const test = require("blue-tape"); const fixtures_1 = require("../tests/fixtures"); const hot_import_1 = require("./hot-import"); // import { log } from 'brolog' // log.level('silly') const EXPECTED_TEXT = 'testing123'; test('callerResolve()', (t) => __awaiter(this, void 0, void 0, function* () { const RELATIVE_FILE_PATH = './test'; const ABSOLUTE_FILE_PATH = path.resolve(__dirname, RELATIVE_FILE_PATH); t.test('relative file path', (t) => __awaiter(this, void 0, void 0, function* () { const filePath = hot_import_1.callerResolve(RELATIVE_FILE_PATH); t.equal(filePath, ABSOLUTE_FILE_PATH, 'should turn relative to absolute'); })); t.test('absolute file path', (t) => __awaiter(this, void 0, void 0, function* () { const filePath = hot_import_1.callerResolve(ABSOLUTE_FILE_PATH); t.equal(filePath, ABSOLUTE_FILE_PATH, 'should keep absolute as it is'); })); t.test('callerExceptFile', (t) => __awaiter(this, void 0, void 0, function* () { const filePath = hot_import_1.callerResolve(RELATIVE_FILE_PATH, __filename); // console.log(filePath) t.assert(filePath.endsWith(path.join(// cross platform: compatible with windows 'node_modules', 'tape', 'lib', 'test')), 'except the current file name'); })); })); test('newCall()', (t) => __awaiter(this, void 0, void 0, function* () { class TextClass { constructor(text) { this.text = text; } } const textClass = hot_import_1.newCall(TextClass, EXPECTED_TEXT); t.equal(textClass.text, EXPECTED_TEXT, 'should instanciate class with constructor arguments'); })); test('hotImport()', (t) => __awaiter(this, void 0, void 0, function* () { t.test('class module(export=)', (t) => __awaiter(this, void 0, void 0, function* () { var e_1, _a; let file, Cls; try { for (var _b = __asyncValues(fixtures_1.changingClassModuleFixtures()), _c; _c = yield _b.next(), !_c.done;) { const info = _c.value; /** * io event loop wait for fs.watch * FIXME: Find out the reason... */ yield new Promise(setImmediate); // the first one is enough for Linux(Ubuntu 17.04) yield new Promise(setImmediate); // the second one is needed for Windows 7 if (!Cls) { file = info.file; Cls = yield hot_import_1.hotImport(file); } else { t.equal(file, info.file, 'should get same module file for fixtures(change file content only)'); } yield new Promise(resolve => setTimeout(resolve, 10)); const result = new Cls(EXPECTED_TEXT); t.equal(result.text, EXPECTED_TEXT, 'should get expected values from instance of class in module'); t.equal(result.id, info.returnValue, 'should import module class with right id:' + info.returnValue); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b); } finally { if (e_1) throw e_1.error; } } if (file) { yield hot_import_1.hotImport(file, false); } })); t.test('variable module(export const answer=)', (t) => __awaiter(this, void 0, void 0, function* () { var e_2, _d; let file, hotMod; try { for (var _e = __asyncValues(fixtures_1.changingVariableModuleFixtures()), _f; _f = yield _e.next(), !_f.done;) { const info = _f.value; /** * io event loop wait for fs.watch * FIXME: Find out the reason... */ yield new Promise(setImmediate); // the first one is enough for Linux(Ubuntu 17.04) with Node.js v8 yield new Promise(setImmediate); // the second one is needed for Windows 7 if (!hotMod) { file = info.file; hotMod = yield hot_import_1.hotImport(file); } else { t.equal(file, info.file, 'should get same module file for fixtures(change file content only)'); } yield new Promise(resolve => setTimeout(resolve, 10)); t.equal(hotMod.answer, info.returnValue, 'should get expected values from variable in module'); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_f && !_f.done && (_d = _e.return)) yield _d.call(_e); } finally { if (e_2) throw e_2.error; } } if (file) { yield hot_import_1.hotImport(file, false); } })); t.test('raw export module(export = () => "value")', (t) => __awaiter(this, void 0, void 0, function* () { var e_3, _g; let file, hotMod; try { for (var _h = __asyncValues(fixtures_1.changingRawFuncModuleFixtures()), _j; _j = yield _h.next(), !_j.done;) { const info = _j.value; /** * io event loop wait for fs.watch * FIXME: Find out the reason... */ yield new Promise(setImmediate); // the first one is enough for Linux(Ubuntu 17.04) with Node.js v8 yield new Promise(setImmediate); // the second one is needed for Windows 7 if (!hotMod) { file = info.file; hotMod = yield hot_import_1.hotImport(file); } else { t.equal(file, info.file, 'should get same module file for fixtures(change file content only)'); } yield new Promise(resolve => setTimeout(resolve, 10)); t.equal(hotMod(), info.returnValue, 'should get expected values from the return value of raw func in module'); } } catch (e_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_j && !_j.done && (_g = _h.return)) yield _g.call(_h); } finally { if (e_3) throw e_3.error; } } if (file) { yield hot_import_1.hotImport(file, false); } })); t.test('module that only has a default export', (t) => __awaiter(this, void 0, void 0, function* () { const EXPECTED_RETURN_VALUE = 42; const DEFAULT_EXPORT_ONLY_MODULE_FILE = '../tests/fixtures/default-export-module'; const mod = yield hot_import_1.hotImport(DEFAULT_EXPORT_ONLY_MODULE_FILE); t.equal(mod(), EXPECTED_RETURN_VALUE, 'should get the default export function return value right'); yield hot_import_1.hotImport(DEFAULT_EXPORT_ONLY_MODULE_FILE, false).catch(() => t.fail('rejected')); })); })); test('importFile()', (t) => __awaiter(this, void 0, void 0, function* () { t.test('const value', (t) => __awaiter(this, void 0, void 0, function* () { var e_4, _k; try { for (var _l = __asyncValues(fixtures_1.changingVariableModuleFixtures()), _m; _m = yield _l.next(), !_m.done;) { const info = _m.value; const hotMod = yield hot_import_1.importFile(info.file); t.equal(hotMod.answer, info.returnValue, 'should import file right with returned value ' + info.returnValue); break; // only test once for importFile } } catch (e_4_1) { e_4 = { error: e_4_1 }; } finally { try { if (_m && !_m.done && (_k = _l.return)) yield _k.call(_l); } finally { if (e_4) throw e_4.error; } } })); t.test('class', (t) => __awaiter(this, void 0, void 0, function* () { var e_5, _o; try { for (var _p = __asyncValues(fixtures_1.changingClassModuleFixtures()), _q; _q = yield _p.next(), !_q.done;) { const info = _q.value; const Module = yield hot_import_1.importFile(info.file); const result = new Module(EXPECTED_TEXT); t.equal(result.text, EXPECTED_TEXT, 'should instanciated class with constructor argument'); t.equal(result.id, info.returnValue, 'should import module class with right id'); break; // only test once for importFile } } catch (e_5_1) { e_5 = { error: e_5_1 }; } finally { try { if (_q && !_q.done && (_o = _p.return)) yield _o.call(_p); } finally { if (e_5) throw e_5.error; } } })); })); test('refreshImport()', (t) => __awaiter(this, void 0, void 0, function* () { var e_6, _r; let cls; try { for (var _s = __asyncValues(fixtures_1.changingClassModuleFixtures()), _t; _t = yield _s.next(), !_t.done;) { const info = _t.value; if (!cls) { cls = yield hot_import_1.importFile(info.file); hot_import_1.moduleStore[info.file] = cls; hot_import_1.proxyStore[info.file] = hot_import_1.initProxyModule(info.file); } else { yield hot_import_1.refreshImport(info.file); t.notEqual(hot_import_1.moduleStore[info.file], cls, 'should be refreshed to new value'); } } } catch (e_6_1) { e_6 = { error: e_6_1 }; } finally { try { if (_t && !_t.done && (_r = _s.return)) yield _r.call(_s); } finally { if (e_6) throw e_6.error; } } })); test('purgeRequireCache()', (t) => __awaiter(this, void 0, void 0, function* () { const KEY = 'test-key'; const VAL = 'test-val'; for (const info of fixtures_1.emptyObjectModuleFixture()) { const m0 = yield hot_import_1.importFile(info.file); t.deepEqual(m0, info.returnValue, 'should get returnValue from module'); m0[KEY] = VAL; const m1 = yield hot_import_1.importFile(info.file); t.equal(m1[KEY], VAL, 'should keep value in require cache'); hot_import_1.purgeRequireCache(info.file); const m2 = yield hot_import_1.importFile(info.file); t.deepEqual(m2, info.returnValue, 'should get returnValue again after purge'); t.equal(m2[KEY], undefined, 'should no KEY exists any more'); } })); test('cloneProperties()', (t) => __awaiter(this, void 0, void 0, function* () { const SRC = { text: EXPECTED_TEXT }; /* eslint padded-blocks: off */ const SRC_CLASS = class { constructor(text) { this.text = text; } }; t.test('object', (t) => __awaiter(this, void 0, void 0, function* () { const dst = {}; hot_import_1.cloneProperties(dst, SRC); t.equal(dst.text, EXPECTED_TEXT, 'should clone the text property'); })); t.test('class', (t) => __awaiter(this, void 0, void 0, function* () { const dst = {}; hot_import_1.cloneProperties(dst, SRC_CLASS); t.equal(SRC_CLASS.prototype, dst.prototype, 'should clone the prototype for class'); })); })); test('VERSION', (t) => __awaiter(this, void 0, void 0, function* () { t.ok(hot_import_1.VERSION.match(/^\d+\.\d+\.\d+$/), 'should get semver version'); t.equal(hot_import_1.VERSION, '0.0.0', 'should be 0.0.0 in source code'); })); //# sourceMappingURL=hot-import.spec.js.map