admin-release.test.mjs 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import {test} from 'node:test';
  2. import assert from 'node:assert/strict';
  3. import fs from 'node:fs/promises';
  4. import path from 'node:path';
  5. import os from 'node:os';
  6. import http from 'node:http';
  7. import {manifestFor,verifyRelease} from '../release-admin-web.mjs';
  8. async function fixture(t){
  9. const dir=await fs.mkdtemp(path.join(os.tmpdir(),'xiaoshu-admin-release-'));
  10. t.after(()=>fs.rm(dir,{recursive:true,force:true}));
  11. await fs.writeFile(path.join(dir,'index.html'),'<!doctype html><script src="main-ABC.js"></script>');
  12. await fs.writeFile(path.join(dir,'main-ABC.js'),'console.log("admin");');
  13. const manifest=await manifestFor(dir,'test-release','source-commit');
  14. await fs.writeFile(path.join(dir,'deployment-version.json'),JSON.stringify(manifest));
  15. return{dir,manifest};
  16. }
  17. async function server(t,dir,override){
  18. const app=http.createServer(async(req,res)=>{
  19. try{
  20. const url=new URL(req.url,'http://localhost'),name=url.pathname.slice(1);
  21. const body=override?.(name);
  22. if(body!==undefined){res.setHeader('Content-Type','text/html');res.end(body);return;}
  23. const file=name.startsWith('admin/')?'index.html':name;
  24. res.setHeader('Content-Type',file.endsWith('.html')?'text/html':file.endsWith('.json')?'application/json':'text/javascript');
  25. res.end(await fs.readFile(path.join(dir,file)));
  26. }catch{res.statusCode=404;res.end('missing');}
  27. });
  28. await new Promise(resolve=>app.listen(0,'127.0.0.1',resolve));
  29. t.after(()=>new Promise(resolve=>app.close(resolve)));
  30. return'http://127.0.0.1:'+app.address().port;
  31. }
  32. test('核对文件哈希和登录/工资深层路由,不能只凭首页成功判断发布成功',async t=>{
  33. const {dir,manifest}=await fixture(t),url=await server(t,dir);
  34. assert.equal((await verifyRelease(url,manifest)).filesVerified,2);
  35. await fs.writeFile(path.join(dir,'main-ABC.js'),'old build');
  36. await assert.rejects(verifyRelease(url,manifest),/文件校验失败/);
  37. });
  38. test('拒绝版本仍旧或深层路由返回其他页面的发布',async t=>{
  39. const {dir,manifest}=await fixture(t),url=await server(t,dir,name=>name==='admin/payroll'?'old index':undefined);
  40. await assert.rejects(verifyRelease(url,manifest),/深层路由/);
  41. await fs.writeFile(path.join(dir,'deployment-version.json'),JSON.stringify({...manifest,releaseId:'old-release'}));
  42. await assert.rejects(verifyRelease(url,manifest),/版本.*不一致/);
  43. });
  44. test('发布包拒绝密钥文件和符号链接',async t=>{
  45. const {dir}=await fixture(t);
  46. await fs.writeFile(path.join(dir,'.env'),'EXAMPLE=private');
  47. await assert.rejects(manifestFor(dir,'r','c'),/不允许/);
  48. await fs.unlink(path.join(dir,'.env'));
  49. await fs.symlink(path.join(dir,'index.html'),path.join(dir,'link'));
  50. await assert.rejects(manifestFor(dir,'r','c'),/不允许/);
  51. });