diff --git a/api/docs/diagrams/sas-execution-handshake.md b/api/docs/diagrams/sas-execution-handshake.md
index ce38924..22b4084 100644
--- a/api/docs/diagrams/sas-execution-handshake.md
+++ b/api/docs/diagrams/sas-execution-handshake.md
@@ -16,6 +16,8 @@ sequenceDiagram
Note over Pool,SAS: SESSION CREATION - happens ahead of any request,
pool pre-warms up to 3 sessions (Session.ts:59-69)
Pool->>FS: createFile(code.sas, "") - empty dummy SYSIN (Session.ts:117-118)
+ Pool->>FS: readFile(sysInitCompiledPath) - compiled system-init
macros, produced by `npm run compileSysInit` (Session.ts:105)
+ Note over Pool: throws if this file doesn't exist yet -
session creation never reaches execFile below
Pool->>FS: createFile(autoexec.sas, autoExecContent) (Session.ts:108-114)
Pool->>SAS: execFile(sasLoc, -SYSIN code.sas -AUTOEXEC autoexec.sas -LOG log.log ...) (Session.ts:127-147)
activate SAS
diff --git a/api/src/routes/api/spec/code.spec.ts b/api/src/routes/api/spec/code.spec.ts
index 6cac058..a65f212 100644
--- a/api/src/routes/api/spec/code.spec.ts
+++ b/api/src/routes/api/spec/code.spec.ts
@@ -1,4 +1,5 @@
import path from 'path'
+import { createFile, fileExists } from '@sasjs/utils'
import { Express } from 'express'
import mongoose, { Mongoose } from 'mongoose'
import { MongoMemoryServer } from 'mongodb-memory-server'
@@ -13,7 +14,8 @@ import {
import {
generateAccessToken,
saveTokensInDB,
- RunTimeType
+ RunTimeType,
+ sysInitCompiledPath
} from '../../../utils'
// Real, unmocked end-to-end test of the SAS execution pipeline (session
@@ -43,6 +45,17 @@ describe('code', () => {
let permissionController: PermissionController
beforeAll(async () => {
+ // SASSessionController.createSession() unconditionally reads this file
+ // (Session.ts:105) before it ever spawns the SAS process. It's normally
+ // produced by `npm run compileSysInit` (part of the `initial`/`build`
+ // scripts), which `npm test` does not run - so on a fresh checkout
+ // (e.g. CI, where "Run Unit Tests" happens before "Build Package") it
+ // doesn't exist yet. Content is irrelevant here since mockSas.js never
+ // interprets it; it just needs to exist and be readable.
+ if (!(await fileExists(sysInitCompiledPath))) {
+ await createFile(sysInitCompiledPath, '')
+ }
+
mongoServer = await MongoMemoryServer.create()
process.env.DB_CONNECT = mongoServer.getUri()
process.env.MODE = 'server'