'use strict'; const assert=require('assert/strict'); const fs=require('fs'); const fsp=fs.promises; const os=require('os'); const path=require('path'); const {spawnSync}=require('child_process'); const BuildMeta=require('../build-meta'); const service=require('../scripts/service-control'); (async()=>{ assert.equal(BuildMeta.APP_VERSION,'48.0'); const root=await fsp.mkdtemp(path.join(os.tmpdir(),'linkfield-v4794-')); const publicDir=path.join(root,'public_html','link-field'); const dataDir=path.join(root,'data'); const logFile=path.join(root,'server.log'); const serviceDir=path.join(root,'service'); const env={...process.env,LINK_FIELD_PUBLIC_DIR:publicDir,LINK_FIELD_TEST_DATA_ROOT:dataDir,LINK_FIELD_TEST_DATA_ROOT:path.join(root,'shared-root'),LINK_FIELD_SERVICE_DIR:serviceDir,LINK_FIELD_LOG_FILE:logFile,PORT:'0'}; try{ await service.deployPublicFiles(publicDir); for(const relative of ['index.html','app.js','runtime-config.js','api-bridge.php','assets','client']){ assert.equal(fs.existsSync(path.join(publicDir,relative)),true,`${relative} was not deployed`); } const manifest=JSON.parse(await fsp.readFile(path.join(publicDir,'.linkfield-deployment.json'),'utf8')); assert.equal(manifest.version,'48.0'); const start=spawnSync(process.execPath,[path.join(service.ROOT,'scripts','service-control.js'),'start'],{cwd:service.ROOT,env,encoding:'utf8',timeout:20_000}); assert.equal(start.status,0,start.stderr||start.stdout); assert.match(start.stdout,/started in the background/i); assert.match(start.stdout,/command prompt is available again/i); const pidFile=path.join(serviceDir,'server.pid'); const pid=Number((await fsp.readFile(pidFile,'utf8')).trim()); assert.equal(service.isProcessRunning(pid),true); const port=Number((await fsp.readFile(path.join(publicDir,'.linkfield-port'),'utf8')).trim()); assert.ok(Number.isSafeInteger(port)&&port>0); const response=await fetch(`http://127.0.0.1:${port}/api/cloud/status`); assert.equal(response.ok,true); const status=await response.json(); assert.equal(status.sharedWorld,true); assert.equal(status.appVersion,'48.0'); assert.equal(fs.existsSync(path.join(publicDir,'.htaccess')),true); const secondStart=spawnSync(process.execPath,[path.join(service.ROOT,'scripts','service-control.js'),'start'],{cwd:service.ROOT,env,encoding:'utf8',timeout:20_000}); assert.equal(secondStart.status,0,secondStart.stderr||secondStart.stdout); assert.match(secondStart.stdout,/Replacing the running LinkField server/i); const replacementPid=Number((await fsp.readFile(pidFile,'utf8')).trim()); assert.notEqual(replacementPid,pid); assert.equal(service.isProcessRunning(pid),false); assert.equal(service.isProcessRunning(replacementPid),true); const stop=spawnSync(process.execPath,[path.join(service.ROOT,'scripts','service-control.js'),'stop'],{cwd:service.ROOT,env,encoding:'utf8',timeout:10_000}); assert.equal(stop.status,0,stop.stderr||stop.stdout); assert.equal(service.isProcessRunning(replacementPid),false); }finally{ spawnSync(process.execPath,[path.join(service.ROOT,'scripts','service-control.js'),'stop'],{cwd:service.ROOT,env,encoding:'utf8',timeout:10_000}); await fsp.rm(root,{recursive:true,force:true}); } console.log('LinkField v48.0 background deployment and service smoke test passed'); })().catch(error=>{console.error(error);process.exitCode=1});