Skip to content

Commit

Permalink
test(SSR e2e): Validate SSR app under test is built in prod mode and …
Browse files Browse the repository at this point in the history
…using a proxy backend, before running tests (#19334)

Problem:
To run SSR Tests, it's necessary to execute: `npm run build` and `npm run build:ssr:local-http-backend` - in order to have an app built in prod mode and using a proxy backend. This step can be easily overlooked by newcomers.
Otherwise, some tests might fail:
- some tests asserting JSON SSR messages might fail - if app built in dev mode which prints JSON logs in multi-line (instead of single-line)
- some tests mocking the backend might fail - if app is not configured to call a Proxy Backend 

Previously, we were checking only if the app is built in prod mode. And we were checking it by symptoms in tests runtime, with the following heuristic: if there's any log line starting with character `{` but not possible to parse as a JSON, then it's probably running in dev mode. In such case were throwing an error.

Now, were checking both if the app is in prod mode and if it's using a backend proxy server. We check it statically before running the tests, with the following heuristics:
- if the build output file `dist/storefrontapp-server/main.js` contains a marker string `CX_BASE_URL:"http://localhost:9002"`, then we know the app is using a local proxy backend
- if the build output file `dist/storefrontapp-server/main.js` contains a marker string `ngDevMode`, then we know the app is build in dev mode

**QA steps:**
**Scenario 1 ❌ - missing `main.js`:**
- remove `dist/storefrontapp-server/main.js`
- run `npm run test:ssr`
- verify the following error message appears before running tests:
   ![image](https://github.com/user-attachments/assets/93a23543-6a26-4922-b478-9363750046ab)

**Scenario 2 ❌ - dev-mode build:**
- run `npm run dev:ssr` and wait until it fully compiles and then kill the process
- run `npm run test:ssr`
- verify the following error message appears before running tests:
   ![image](https://github.com/user-attachments/assets/48eaae99-16a0-46a0-b5df-131541fa11c1)

**Scenario 3 ❌ - prod-mode build BUT not using local http proxy backend:**
- run `npm run build && npm run build:ssr`
- run `npm run test:ssr`
- verify the following error message appears before running tests:
   ![image](https://github.com/user-attachments/assets/28cae1ab-07e5-42ff-9edb-4448b8326cef)

**Scenario 4 ✅ - prod-mode build AND  using local http proxy backend:**
- run `npm run build && npm run build:ssr`
- run `npm run test:ssr`
- verify the tests run successfully:
   ![image](https://github.com/user-attachments/assets/14dbf112-c9c1-4aac-9f82-ca5dbf31600e)

closes https://jira.tools.sap/browse/CXSPA-8586
  • Loading branch information
Platonn authored Oct 4, 2024
1 parent a6f91eb commit 81c7302
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 27 deletions.
1 change: 1 addition & 0 deletions projects/ssr-tests/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ module.exports = {
},
},
testEnvironment: './src/environments/custom-test-environment.ts',
globalSetup: './validate-ssr-build.ts',
};
27 changes: 0 additions & 27 deletions projects/ssr-tests/src/utils/log.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
84 changes: 84 additions & 0 deletions projects/ssr-tests/validate-ssr-build.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* SPDX-FileCopyrightText: 2024 SAP Spartacus team <[email protected]>
*
* 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`;
}

0 comments on commit 81c7302

Please sign in to comment.