diff --git a/projects/ssr-tests/jest.config.js b/projects/ssr-tests/jest.config.js index f0aea45398b..9216d61df84 100644 --- a/projects/ssr-tests/jest.config.js +++ b/projects/ssr-tests/jest.config.js @@ -23,4 +23,5 @@ module.exports = { }, }, testEnvironment: './src/environments/custom-test-environment.ts', + globalSetup: './validate-ssr-build.ts', }; diff --git a/projects/ssr-tests/src/utils/log.utils.ts b/projects/ssr-tests/src/utils/log.utils.ts index 654acff728d..e722b5c6c69 100644 --- a/projects/ssr-tests/src/utils/log.utils.ts +++ b/projects/ssr-tests/src/utils/log.utils.ts @@ -25,41 +25,14 @@ export function clearSsrLogFile(): void { fs.writeFileSync(SSR_LOG_PATH, ''); } -/** - * Validates that all lines starting with `{` are valid JSON objects. - * Otherwise it throws an error. - * - * Note: multi-line JSONs (printed by SSR in dev mode) cannot be parsed by `JSON.parse`. - * That's why we need to to run SSR in prod mode to get single line JSON logs. - */ -function validateJsonsInLogs(logs: string[]): void { - logs.forEach((text) => { - if (text.charAt(0) === '{') { - try { - JSON.parse(text); - } catch (error) { - throw new Error( - `Encountered in SSR Logs a line starting with \`{\` that could not be parsed as JSON. - Perhaps its a multi-line JSON log from SSR dev mode. - Please make sure to build Spartacus SSR in prod mode - to get single line JSONs that can be parsed in tests.` - ); - } - } - }); -} - /** * Returns raw logs as an array of strings. * * Note: Non-JSON log entries are also included in the returned array. - * - * It also validates whether each line starting with `{` is a valid JSON object. - * Otherwise it throws an error. */ export function getRawLogs(): string[] { const data = fs.readFileSync(SSR_LOG_PATH).toString(); const logs = data.toString().split('\n'); - validateJsonsInLogs(logs); return logs; } diff --git a/projects/ssr-tests/validate-ssr-build.ts b/projects/ssr-tests/validate-ssr-build.ts new file mode 100644 index 00000000000..7430b00c2eb --- /dev/null +++ b/projects/ssr-tests/validate-ssr-build.ts @@ -0,0 +1,84 @@ +/* + * SPDX-FileCopyrightText: 2024 SAP Spartacus team + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * Verify that the SSR app under tests meets the following criteria: + * 1. The app us built in prod mode. + * + * Why it's needed: + * Some tests require parsing single-line JSON log entries appearing in the SSR logs. + * In an app built in prod mode, the JSON objects are printed single-line that can be easily parsed in tests. + * In an app built in dev mode, the JSON objects are printed multi-line (to be more human-readable), + * but cannot be parsed in tests so it makes some tests to fail. + * + * 2. The app has configured a base OCC url being a local backend proxy, instead of a real backend. + * + * Why it's needed: + * Some tests require mocking the behavior of the backend using a local backend http proxy. + * If the app is not calling a local backend proxy as a base OCC url, some tests will fail. + * + * + * In this file we'll validate the build of the app before running the tests. + */ + +import * as fs from 'fs'; +import * as path from 'path'; + +/** + * String that always appears in the `main.js` file of the SSR app when built with a local backend proxy. + */ +const USING_PROXY_BACKEND_MARKER = `CX_BASE_URL:"http://localhost:9002"`; + +/** + * String that always appears in the `main.js` file of the SSR app when built in dev mode. + */ +const USING_DEV_MODE_MARKER = `ngDevMode`; + +/** + * Path to the `main.js` file of the built SSR app. + */ +const SSR_APP_PATH = path.join( + __dirname, + '../../dist/storefrontapp-server/main.js' +); + +/** + * Advice to the user on how to build the SSR app in prod mode to use a local backend proxy. + */ +const BUILD_COMMAND_ADVICE = + colorToYellow('Please build the SSR app with the following command\n') + + colorToYellow('> npm run build && npm run build:ssr:local-http-backend\n'); + +export default async function validateSsrBuild() { + if (!fs.existsSync(SSR_APP_PATH)) { + throw new Error( + ` +SSR app not found at the expected path '${SSR_APP_PATH}'. +${BUILD_COMMAND_ADVICE}` + ); + } + + const fileContents = fs.readFileSync(SSR_APP_PATH, 'utf8'); + if (!fileContents.includes(USING_PROXY_BACKEND_MARKER)) { + throw new Error( + ` +SSR app is not using a local backend proxy as a base OCC url. +${BUILD_COMMAND_ADVICE}` + ); + } + + if (fileContents.includes(USING_DEV_MODE_MARKER)) { + throw new Error( + ` +SSR app is not using prod mode. +${BUILD_COMMAND_ADVICE}` + ); + } +} + +function colorToYellow(text: string) { + return `\x1b[33m${text}\x1b[0m`; +}