verify-change-lifecycle.cjs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. 'use strict';
  2. const assert = require('node:assert/strict');
  3. const fs = require('node:fs');
  4. const path = require('node:path');
  5. const vm = require('node:vm');
  6. /**
  7. * @param {string} source - 页面源码
  8. * @param {string} name - 导出函数名
  9. * @returns {string} 可独立执行的函数源码
  10. */
  11. function extractFunction(source, name) {
  12. const pattern = new RegExp('export function ' + name + '\\(');
  13. const match = pattern.exec(source);
  14. assert.ok(match, '缺少方法 ' + name);
  15. const nextExport = source.indexOf('\nexport function ', match.index + match[0].length);
  16. return source.slice(match.index, nextExport < 0 ? source.length : nextExport).replace(/^export /, '');
  17. }
  18. const sourcePath = process.argv[2]
  19. ? path.resolve(process.argv[2])
  20. : path.resolve(__dirname, '../src/timecard-change.oyd.jsx');
  21. const source = fs.readFileSync(sourcePath, 'utf8');
  22. assert.doesNotMatch(source, /window\._this/, '变更页渲染不得依赖跨页面共享的 window._this');
  23. assert.match(source, /var _this = this;[\s\S]*if \(!_this \|\| !_this\.state/,
  24. 'renderJsx 应使用当前页面实例');
  25. let removedEvent = null;
  26. let removedHandler = null;
  27. const methods = vm.runInNewContext(
  28. ['refreshTimecardView', 'forceUpdate', 'didUnmount']
  29. .map((name) => extractFunction(source, name)).join('\n')
  30. + '\n({refreshTimecardView, forceUpdate, didUnmount})',
  31. {
  32. window: {
  33. removeEventListener(event, handler) {
  34. removedEvent = event;
  35. removedHandler = handler;
  36. },
  37. },
  38. },
  39. );
  40. const resizeHandler = () => {};
  41. let setStateCount = 0;
  42. let forceUpdateCount = 0;
  43. const context = {
  44. _tcDisposed: false,
  45. _tcBeisenLeaveRequestKey: 'active-request',
  46. _tcResizeHandler: resizeHandler,
  47. setState() { setStateCount += 1; },
  48. forceUpdate() { forceUpdateCount += 1; },
  49. };
  50. methods.didUnmount.call(context);
  51. assert.equal(context._tcDisposed, true);
  52. assert.equal(context._tcBeisenLeaveRequestKey, '__TIMECARD_PAGE_DISPOSED__');
  53. assert.equal(context._tcResizeHandler, null);
  54. assert.equal(removedEvent, 'resize');
  55. assert.equal(removedHandler, resizeHandler);
  56. methods.refreshTimecardView.call(context);
  57. methods.forceUpdate.call(context);
  58. assert.equal(forceUpdateCount, 0, '卸载后不得继续 forceUpdate');
  59. assert.equal(setStateCount, 0, '卸载后不得继续 setState');
  60. console.log('PASS 变更页面切换时清理实例、监听和异步刷新');