Skip to content

Commit

Permalink
test: SSR E2E Test Scenarios (#17666)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zeyber authored Oct 3, 2023
1 parent db9157b commit 37239d3
Show file tree
Hide file tree
Showing 19 changed files with 475 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .env-cmdrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"local": {
"CX_BASE_URL": "https://localhost:9002"
},
"local-http": {
"CX_BASE_URL": "http://localhost:9002"
},
"ci": {
"CX_BASE_URL": "https://20.83.184.244:9002"
},
Expand Down
27 changes: 26 additions & 1 deletion .github/workflows/ci-merge-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,32 @@ jobs:
BUILD_NUMBER: ci-build-number-${{ github.event.pull_request.head.sha || github.run_id }}
run: |
ci-scripts/e2e-cypress.sh -s b2b
ssr_tests:
needs: [no_retries, validate_e2e_execution]
name: MC - SSR tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v2
with:
path: |
node_modules
key: nodemodules-${{ github.event.pull_request.base.sha }}
restore-keys: nodemodules-${{ github.event.pull_request.base.sha }}
- name: Package installation
run: npm ci
- name: Build SSR Server
run: npm run build:libs && npm run build && npm run build:ssr:local-http
- name: Run SSR tests
run: npm run test:ssr:ci --verbose
merge_checks_result:
needs: [b2c_e2e_tests, b2c_ssr_e2e_tests, b2b_e2e_tests]
needs: [b2c_e2e_tests, b2c_ssr_e2e_tests, b2b_e2e_tests, ssr_tests]
name: MC - Result
runs-on: ubuntu-latest
if: ${{ always() }}
Expand All @@ -163,4 +187,5 @@ jobs:
if: |
needs.b2c_e2e_tests.result == 'failure' || needs.b2c_e2e_tests.result == 'cancelled' ||
needs.b2c_ssr_e2e_tests.result == 'failure' || needs.b2c_ssr_e2e_tests.result == 'cancelled' ||
needs.ssr_tests.result == 'failure' || needs.ssr_tests.result == 'cancelled' ||
needs.b2b_e2e_tests.result == 'failure' || needs.b2b_e2e_tests.result == 'cancelled'
27 changes: 26 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -216,8 +216,32 @@ jobs:
BUILD_NUMBER: ci-build-number-${{ github.event.pull_request.head.sha || github.run_id }}
run: |
ci-scripts/e2e-cypress.sh -s b2b
ssr_tests:
needs: [no_retries, validate_e2e_execution]
name: SSR Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ env.NODE_VERSION }}
- name: Cache node_modules
id: cache-node-modules
uses: actions/cache@v2
with:
path: |
node_modules
key: nodemodules-${{ github.event.pull_request.base.sha }}
restore-keys: nodemodules-${{ github.event.pull_request.base.sha }}
- name: Package installation
run: npm ci
- name: Build SSR Server
run: npm run build:libs && npm run build && npm run build:ssr:local-http
- name: Run SSR tests
run: npm run test:ssr:ci --verbose
build_conclusion:
needs: [no_retries, unit_tests, linting, b2c_e2e_tests, b2c_ssr_e2e_tests, b2b_e2e_tests, sonarqube_scan]
needs: [no_retries, unit_tests, linting, b2c_e2e_tests, b2c_ssr_e2e_tests, b2b_e2e_tests, ssr_tests, sonarqube_scan]
name: Build Conclusion
runs-on: ubuntu-latest
if: ${{ always() }}
Expand All @@ -234,6 +258,7 @@ jobs:
needs.linting.result == 'failure' || needs.linting.result == 'cancelled' ||
needs.b2c_e2e_tests.result == 'failure' || needs.b2c_e2e_tests.result == 'cancelled' ||
needs.b2c_ssr_e2e_tests.result == 'failure' || needs.b2c_ssr_e2e_tests.result == 'cancelled' ||
needs.ssr_tests.result == 'failure' || needs.ssr_tests.result == 'cancelled' ||
needs.b2b_e2e_tests.result == 'failure' || needs.b2b_e2e_tests.result == 'cancelled'
send_slack_message:
needs: build_conclusion
Expand Down
2 changes: 1 addition & 1 deletion ci-scripts/unit-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -e
set -o pipefail

EXCLUDE_APPLICATIONS=storefrontapp
EXCLUDE_APPLICATIONS=storefrontapp,ssr-tests
EXCLUDE_JEST=storefrontstyles,schematics,setup

echo "-----"
Expand Down
4 changes: 3 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"build:setup": "nx build setup --configuration production",
"build:ssr": "env-cmd --no-override -e dev,b2c,$SPA_ENV nx run storefrontapp:server:production",
"build:ssr:ci": "env-cmd -e ci,b2c,$SPA_ENV nx run storefrontapp:server:production",
"build:ssr:local-http": "env-cmd -e local-http,b2c,$SPA_ENV nx run storefrontapp:server:production",
"build:storefinder": "npm --prefix feature-libs/storefinder run build:schematics && nx build storefinder --configuration production",
"build:smartedit": "npm --prefix feature-libs/smartedit run build:schematics && nx build smartedit --configuration production",
"build:tracking": "npm --prefix feature-libs/tracking run build:schematics && nx build tracking --configuration production",
Expand Down Expand Up @@ -87,6 +88,8 @@
"test:storefront:lib": "nx test storefrontlib --source-map --code-coverage",
"dev:ssr": "env-cmd --no-override -e dev,b2c,$SPA_ENV cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 nx run storefrontapp:serve-ssr",
"serve:ssr": "node dist/storefrontapp-server/main.js",
"test:ssr": "env-cmd -e dev nx test ssr-tests",
"test:ssr:ci": "env-cmd -e ci nx test ssr-tests",
"serve:ssr:ci": "NODE_TLS_REJECT_UNAUTHORIZED=0 SSR_TIMEOUT=0 node dist/storefrontapp-server/main.js",
"serve:ssr:dev": "cross-env NODE_TLS_REJECT_UNAUTHORIZED=0 node dist/storefrontapp-server/main.js",
"prerender": "nx run storefrontapp:prerender --routes-file projects/storefrontapp/prerender.txt",
Expand Down Expand Up @@ -183,6 +186,7 @@
"eslint-plugin-prefer-arrow": "^1.2.3",
"fs-extra": "^11.1.1",
"glob": "^7.1.6",
"http-proxy": "^1.18.1",
"http-server": "^14.1.1",
"i18n-lint": "^1.1.0",
"jasmine-core": "~4.6.0",
Expand Down
3 changes: 3 additions & 0 deletions projects/schematics/src/dependencies.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
"parse5": "^6.0.1",
"typescript": "^4.8.2"
},
"ssr-tests": {
"http-proxy": "^1.18.1"
},
"storefrontapp-e2e-cypress": {},
"@spartacus/storefront": {
"@angular/common": "^15.2.9",
Expand Down
3 changes: 2 additions & 1 deletion projects/schematics/src/shared/utils/graph-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ export function kahnsAlgorithm(graph: Graph): string[] {
function createLibraryDependencyGraph(): Graph {
const skip = CORE_SPARTACUS_SCOPES.concat(
'storefrontapp-e2e-cypress',
'storefrontapp'
'storefrontapp',
'ssr-tests'
);

const spartacusLibraries = Object.keys(collectedDependencies).filter(
Expand Down
12 changes: 12 additions & 0 deletions projects/ssr-tests/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"extends": "../../.eslintrc.json",
"ignorePatterns": ["**/*.d.ts"],
"overrides": [
{
"files": ["*.ts"],
"rules": {
"no-console": "off"
}
}
]
}
1 change: 1 addition & 0 deletions projects/ssr-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ssr.log
35 changes: 35 additions & 0 deletions projects/ssr-tests/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig.json');
const { defaultTransformerOptions } = require('jest-preset-angular/presets');

/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
module.exports = {
preset: 'jest-preset-angular',
globalSetup: 'jest-preset-angular/global-setup',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>/',
}),
setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
testMatch: ['**/+(*.)+(spec).+(ts)'],
transform: {
'^.+\\.(ts|js|mjs|html|svg)$': [
'jest-preset-angular',
{
...defaultTransformerOptions,
tsconfig: '<rootDir>/tsconfig.json',
},
],
},

collectCoverage: false,
coverageReporters: ['json', 'lcov', 'text', 'clover'],
coverageDirectory: '<rootDir>/../../coverage/ssr-tests',
coverageThreshold: {
global: {
statements: 90,
branches: 74,
functions: 90,
lines: 90,
},
},
};
21 changes: 21 additions & 0 deletions projects/ssr-tests/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "ssr-tests",
"description": "Spartacus SSR Tests",
"keywords": [
"spartacus",
"ssr",
"tests"
],
"author": "SAP, Spartacus team",
"license": "Apache-2.0",
"private": true,
"scripts": {
"test": "../../node_modules/.bin/jest --config ./jest.config.js"
},
"dependencies": {
"tslib": "^2.6.2"
},
"peerDependencies": {
"http-proxy": "^1.18.1"
}
}
22 changes: 22 additions & 0 deletions projects/ssr-tests/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "ssr-tests",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "projects/ssr-tests/src",
"projectType": "library",
"targets": {
"lint": {
"executor": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["projects/ssr-tests/**/*.ts"]
}
},
"test-jest": {
"executor": "nx:run-commands",
"options": {
"command": "npm run test",
"cwd": "projects/ssr-tests"
}
}
},
"tags": ["type:util"]
}
8 changes: 8 additions & 0 deletions projects/ssr-tests/setup-jest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* SPDX-FileCopyrightText: 2023 SAP Spartacus team <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

import 'jest-preset-angular/setup-jest';
import 'zone.js';
85 changes: 85 additions & 0 deletions projects/ssr-tests/src/log.utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* SPDX-FileCopyrightText: 2023 SAP Spartacus team <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* Contains methods pertaining to reading, writing and asserting of the ssr log
* generated by a running ssr server for the sake of testing ssr.
*/

import * as fs from 'fs';

/**
* Path where SSR log file from server will be generated and read from.
*/
const SSR_LOG_PATH = './ssr.log';

/**
* Writes no characters to log to clear log file.
*/
export function clearSsrLogFile(): void {
fs.writeFileSync(SSR_LOG_PATH, '');
}

/**
* Returns all text in the log as a single string.
*/
export function getLogText(): string {
return fs.readFileSync(SSR_LOG_PATH).toString();
}

/**
* Reads log and returns messages as string array.
*/
export function getLogMessages(): string[] {
const data = fs.readFileSync(SSR_LOG_PATH).toString();
return (
data
.toString()
.split('\n')
// We're interested only in JSON logs from Spartacus SSR app.
// We ignore plain text logs coming from other sources, like `Node Express server listening on http://localhost:4200`
.filter((text: string) => text.charAt(0) === '{')
.map((text: any) => JSON.parse(text).message)
);
}

/**
* Check that log contains expected messages in string array.
* Fail test if log does not contain expected messages.
*/
export function assertMessages(expected: string[]): void {
const messages = getLogMessages();
for (const message of expected) {
expect(messages).toContain(message);
}
}

/**
* Check log every interval to see if log contains text.
* Keeps waiting until log contains text or test times out.
*/
export async function waitUntilLogContainsText(
text: string,
checkInterval = 500
): Promise<true> {
return new Promise((resolve) => {
if (doesLogContainText(text)) {
return resolve(true);
}
return setTimeout(
() => resolve(waitUntilLogContainsText(text)),
checkInterval
);
});
}

/**
* Returns true if log contains string.
*/
export function doesLogContainText(text: string): boolean {
const data = fs.readFileSync(SSR_LOG_PATH).toString();
return data.includes(text);
}
Loading

0 comments on commit 37239d3

Please sign in to comment.