@salesforce/pwa-kit-runtime 3.17.0 → 3.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/pwa-kit-runtime",
|
|
3
|
-
"version": "3.17.
|
|
3
|
+
"version": "3.17.1",
|
|
4
4
|
"description": "The PWAKit Runtime",
|
|
5
5
|
"homepage": "https://github.com/SalesforceCommerceCloud/pwa-kit/tree/develop/packages/pwa-kit-runtime#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -48,11 +48,11 @@
|
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@loadable/component": "^5.15.3",
|
|
51
|
-
"@salesforce/pwa-kit-dev": "3.17.
|
|
51
|
+
"@salesforce/pwa-kit-dev": "3.17.1",
|
|
52
52
|
"@serverless/event-mocks": "^1.1.1",
|
|
53
53
|
"aws-lambda-mock-context": "^3.2.1",
|
|
54
54
|
"fs-extra": "^11.1.1",
|
|
55
|
-
"internal-lib-build": "3.17.
|
|
55
|
+
"internal-lib-build": "3.17.1",
|
|
56
56
|
"nock": "^13.3.0",
|
|
57
57
|
"nodemon": "^2.0.22",
|
|
58
58
|
"sinon": "^13.0.2",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"supertest": "^4.0.2"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
|
-
"@salesforce/pwa-kit-dev": "3.17.
|
|
63
|
+
"@salesforce/pwa-kit-dev": "3.17.1"
|
|
64
64
|
},
|
|
65
65
|
"peerDependenciesMeta": {
|
|
66
66
|
"@salesforce/pwa-kit-dev": {
|
|
@@ -74,5 +74,5 @@
|
|
|
74
74
|
"publishConfig": {
|
|
75
75
|
"directory": "dist"
|
|
76
76
|
},
|
|
77
|
-
"gitHead": "
|
|
77
|
+
"gitHead": "d09ed57f84432913ab3e55e3073802d319c5dc3c"
|
|
78
78
|
}
|
|
@@ -27,6 +27,7 @@ var _loggerInstance = _interopRequireDefault(require("../../utils/logger-instanc
|
|
|
27
27
|
var _httpProxyMiddleware = require("http-proxy-middleware");
|
|
28
28
|
var _hybridProxy = require("../../utils/ssr-server/hybrid-proxy");
|
|
29
29
|
var _convertExpressRoute = require("../../utils/ssr-server/convert-express-route");
|
|
30
|
+
var _ssrConfig = require("../../utils/ssr-config");
|
|
30
31
|
var _serverlessAdapter = require("@h4ad/serverless-adapter");
|
|
31
32
|
var _default = require("@h4ad/serverless-adapter/lib/handlers/default");
|
|
32
33
|
var _callback = require("@h4ad/serverless-adapter/lib/resolvers/callback");
|
|
@@ -445,6 +446,7 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
|
|
|
445
446
|
* @private
|
|
446
447
|
*/
|
|
447
448
|
_setupBasePathMiddleware(app) {
|
|
449
|
+
var _getConfig, _getConfig$app, _getConfig$app$url;
|
|
448
450
|
// Cache the express route regexes to avoid re-calculating them on every request.
|
|
449
451
|
let expressRouteRegexes;
|
|
450
452
|
|
|
@@ -490,11 +492,19 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
|
|
|
490
492
|
* If the server receives a request containing the base path, remove it before allowing
|
|
491
493
|
* the request through to the other express endpoints
|
|
492
494
|
*
|
|
493
|
-
* We scope base path removal to /mobify routes
|
|
494
|
-
* (For example /callback or /worker.js)
|
|
495
|
+
* We scope base path removal to /mobify routes, /__pwa-kit routes (when showBasePath
|
|
496
|
+
* is false), and routes defined by the express app (For example /callback or /worker.js).
|
|
495
497
|
* This is to avoid affecting React Router routes where a site id or locale might be present
|
|
496
498
|
* that is equal to the base path.
|
|
497
499
|
*
|
|
500
|
+
* /__pwa-kit routes are a special case. These are internal PWA Kit routes
|
|
501
|
+
* (e.g. /__pwa-kit/refresh) that are registered as React Router routes and are invoked
|
|
502
|
+
* by the Storefront Preview code on Runtime Admin (which always appends a base path if set).
|
|
503
|
+
* When showBasePath is false, React Router has no basename, so we redirect to the clean
|
|
504
|
+
* URL (without base path) so the browser navigates to a path that React Router can match
|
|
505
|
+
* and hydrate correctly on the client.
|
|
506
|
+
* When showBasePath is true, React Router handles the base path via its basename prop.
|
|
507
|
+
*
|
|
498
508
|
* For example, if you have a base path of /us and a site id of /us we don't want
|
|
499
509
|
* to remove the /us from www.example.com/us/en-US/category/... as this route is handled by
|
|
500
510
|
* React Router and the PWA multisite implementation.
|
|
@@ -502,6 +512,7 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
|
|
|
502
512
|
* @param req {express.req} the incoming request - modified in-place
|
|
503
513
|
* @private
|
|
504
514
|
*/
|
|
515
|
+
const showBasePath = ((_getConfig = (0, _ssrConfig.getConfig)()) === null || _getConfig === void 0 ? void 0 : (_getConfig$app = _getConfig.app) === null || _getConfig$app === void 0 ? void 0 : (_getConfig$app$url = _getConfig$app.url) === null || _getConfig$app$url === void 0 ? void 0 : _getConfig$app$url.showBasePath) === true;
|
|
505
516
|
const removeBasePathMiddleware = (req, res, next) => {
|
|
506
517
|
const basePath = (0, _ssrNamespacePaths.getEnvBasePath)();
|
|
507
518
|
|
|
@@ -515,8 +526,20 @@ const RemoteServerFactory = exports.RemoteServerFactory = {
|
|
|
515
526
|
return next();
|
|
516
527
|
}
|
|
517
528
|
|
|
518
|
-
//
|
|
519
|
-
|
|
529
|
+
// /__pwa-kit routes: when showBasePath is false, the browser URL still has the
|
|
530
|
+
// base path but client-side React Router has no basename, so hydration would fail.
|
|
531
|
+
// Redirect to the clean URL so the browser navigates to a path React Router matches.
|
|
532
|
+
if (!showBasePath && req.path.startsWith(`${basePath}/__pwa-kit`)) {
|
|
533
|
+
const cleanPath = removeBasePathFromPath(req.path);
|
|
534
|
+
const {
|
|
535
|
+
search
|
|
536
|
+
} = (0, _ssrServer.parseRequestUrl)(req);
|
|
537
|
+
return res.redirect(302, cleanPath + search);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
// For other routes, only proceed if path equals basePath or path starts with basePath + '/'
|
|
541
|
+
const pathMatchesBasePath = req.path === basePath || req.path.startsWith(basePath + '/');
|
|
542
|
+
if (!pathMatchesBasePath) {
|
|
520
543
|
return next();
|
|
521
544
|
}
|
|
522
545
|
|
|
@@ -13,6 +13,7 @@ var _ssrCache = require("../../utils/ssr-cache");
|
|
|
13
13
|
var _ssrServer = require("../../utils/ssr-server");
|
|
14
14
|
var ssrServerUtils = _interopRequireWildcard(require("../../utils/ssr-server/utils"));
|
|
15
15
|
var ssrConfig = _interopRequireWildcard(require("../../utils/ssr-config"));
|
|
16
|
+
var ssrNamespacePaths = _interopRequireWildcard(require("../../utils/ssr-namespace-paths"));
|
|
16
17
|
var _buildRemoteServer = require("./build-remote-server");
|
|
17
18
|
var _constants = require("./constants");
|
|
18
19
|
var _express2 = require("./express");
|
|
@@ -1191,10 +1192,16 @@ describe('SLAS private client proxy', () => {
|
|
|
1191
1192
|
}));
|
|
1192
1193
|
});
|
|
1193
1194
|
describe('Base path tests', () => {
|
|
1195
|
+
beforeEach(() => {
|
|
1196
|
+
// Re-establish the getConfig mock that afterEach's restoreAllMocks clears.
|
|
1197
|
+
// _setupBasePathMiddleware reads getConfig() at setup time.
|
|
1198
|
+
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({});
|
|
1199
|
+
});
|
|
1200
|
+
afterEach(() => {
|
|
1201
|
+
jest.restoreAllMocks();
|
|
1202
|
+
});
|
|
1194
1203
|
test('Base path is removed from /mobify request path and still gets through to /mobify endpoint', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1195
|
-
jest.spyOn(
|
|
1196
|
-
envBasePath: '/basepath'
|
|
1197
|
-
});
|
|
1204
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1198
1205
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1199
1206
|
return (0, _supertest.default)(app).get('/basepath/mobify/ping').then(response => {
|
|
1200
1207
|
expect(response.status).toBe(200);
|
|
@@ -1202,9 +1209,7 @@ describe('Base path tests', () => {
|
|
|
1202
1209
|
}), 15000);
|
|
1203
1210
|
test('should not remove base path from non /mobify non-express routes', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1204
1211
|
// Set base path to something that might also be a site id used by react router routes
|
|
1205
|
-
jest.spyOn(
|
|
1206
|
-
envBasePath: '/us'
|
|
1207
|
-
});
|
|
1212
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/us');
|
|
1208
1213
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1209
1214
|
|
|
1210
1215
|
// Add a middleware to capture the request path after base path processing
|
|
@@ -1221,9 +1226,7 @@ describe('Base path tests', () => {
|
|
|
1221
1226
|
});
|
|
1222
1227
|
}), 15000);
|
|
1223
1228
|
test('should remove base path from routes with path parameters', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1224
|
-
jest.spyOn(
|
|
1225
|
-
envBasePath: '/basepath'
|
|
1226
|
-
});
|
|
1229
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1227
1230
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1228
1231
|
app.get('/api/users/:id', (req, res) => {
|
|
1229
1232
|
res.status(200).json({
|
|
@@ -1236,9 +1239,7 @@ describe('Base path tests', () => {
|
|
|
1236
1239
|
});
|
|
1237
1240
|
}), 15000);
|
|
1238
1241
|
test('should remove base path from routes defined with regex', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1239
|
-
jest.spyOn(
|
|
1240
|
-
envBasePath: '/basepath'
|
|
1241
|
-
});
|
|
1242
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1242
1243
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1243
1244
|
app.get(/\/api\/users\/\d+/, (req, res) => {
|
|
1244
1245
|
// Extract the user ID from the URL path since regex routes don't create req.params automatically
|
|
@@ -1253,25 +1254,8 @@ describe('Base path tests', () => {
|
|
|
1253
1254
|
expect(response.body.userId).toBe('123');
|
|
1254
1255
|
});
|
|
1255
1256
|
}), 15000);
|
|
1256
|
-
test('remove base path can handle multi-part base paths', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1257
|
-
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
1258
|
-
envBasePath: '/my/base/path'
|
|
1259
|
-
});
|
|
1260
|
-
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1261
|
-
app.get('/api/test', (req, res) => {
|
|
1262
|
-
res.status(200).json({
|
|
1263
|
-
message: 'test'
|
|
1264
|
-
});
|
|
1265
|
-
});
|
|
1266
|
-
return (0, _supertest.default)(app).get('/my/base/path/api/test').then(response => {
|
|
1267
|
-
expect(response.status).toBe(200);
|
|
1268
|
-
expect(response.body.message).toBe('test');
|
|
1269
|
-
});
|
|
1270
|
-
}), 15000);
|
|
1271
1257
|
test('should handle optional characters in route pattern', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1272
|
-
jest.spyOn(
|
|
1273
|
-
envBasePath: '/basepath'
|
|
1274
|
-
});
|
|
1258
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1275
1259
|
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1276
1260
|
|
|
1277
1261
|
// This route is intentionally made complex to test the following:
|
|
@@ -1289,4 +1273,39 @@ describe('Base path tests', () => {
|
|
|
1289
1273
|
expect(response.body.message).toBe('test');
|
|
1290
1274
|
});
|
|
1291
1275
|
}), 15000);
|
|
1276
|
+
test('should redirect /__pwa-kit routes to clean URL when showBasePath is false', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1277
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1278
|
+
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
1279
|
+
app: {
|
|
1280
|
+
url: {
|
|
1281
|
+
showBasePath: false
|
|
1282
|
+
}
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1285
|
+
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1286
|
+
return (0, _supertest.default)(app).get('/basepath/__pwa-kit/refresh?referrer=/some-page').expect(302).then(response => {
|
|
1287
|
+
// Should redirect to the clean URL without base path
|
|
1288
|
+
expect(response.headers.location).toBe('/__pwa-kit/refresh?referrer=/some-page');
|
|
1289
|
+
});
|
|
1290
|
+
}), 15000);
|
|
1291
|
+
test('should not remove base path from /__pwa-kit routes when showBasePath is true', /*#__PURE__*/_asyncToGenerator(function* () {
|
|
1292
|
+
jest.spyOn(ssrNamespacePaths, 'getEnvBasePath').mockReturnValue('/basepath');
|
|
1293
|
+
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
1294
|
+
app: {
|
|
1295
|
+
url: {
|
|
1296
|
+
showBasePath: true
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
const app = _buildRemoteServer.RemoteServerFactory._createApp(opts());
|
|
1301
|
+
let capturedPath = null;
|
|
1302
|
+
app.use((req, res, next) => {
|
|
1303
|
+
capturedPath = req.path;
|
|
1304
|
+
next();
|
|
1305
|
+
});
|
|
1306
|
+
return (0, _supertest.default)(app).get('/basepath/__pwa-kit/refresh').then(() => {
|
|
1307
|
+
// Base path should NOT be stripped since React Router handles it via basename
|
|
1308
|
+
expect(capturedPath).toBe('/basepath/__pwa-kit/refresh');
|
|
1309
|
+
});
|
|
1310
|
+
}), 15000);
|
|
1292
1311
|
});
|
|
@@ -4,9 +4,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.ssrNamespace = exports.slasPrivateProxyPath = exports.proxyBasePath = exports.healthCheckPath = exports.getEnvBasePath = exports.cachingBasePath = exports.bundleBasePath = void 0;
|
|
7
|
-
var _ssrConfig = require("./ssr-config");
|
|
8
|
-
var _loggerInstance = _interopRequireDefault(require("./logger-instance"));
|
|
9
|
-
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
7
|
/*
|
|
11
8
|
* Copyright (c) 2025, salesforce.com, inc.
|
|
12
9
|
* All rights reserved.
|
|
@@ -32,35 +29,39 @@ const SLAS_PRIVATE_CLIENT_PROXY_PATH = `${MOBIFY_PATH}/slas/private`;
|
|
|
32
29
|
|
|
33
30
|
/*
|
|
34
31
|
* Returns the base path. This is prepended to a /mobify path.
|
|
35
|
-
* Returns an empty string if the base path is not set
|
|
32
|
+
* Returns an empty string if the base path is not set.
|
|
33
|
+
* Throws an error if the base path is not valid.
|
|
34
|
+
*
|
|
35
|
+
* Use this function if you are working with an express route
|
|
36
|
+
* (ie. The route is defined in ssr.js).
|
|
37
|
+
*
|
|
38
|
+
* Use getRouterBasePath (pwa-kit-react-sdk) if you are working
|
|
39
|
+
* with a React Router route
|
|
40
|
+
* (ie. The route is defined in routes.jsx).
|
|
36
41
|
*/
|
|
37
42
|
const getEnvBasePath = () => {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
});
|
|
44
|
-
return '';
|
|
43
|
+
let basePath = '';
|
|
44
|
+
if (typeof window !== 'undefined') {
|
|
45
|
+
basePath = window.__MRT_ENV_BASE_PATH__ || '';
|
|
46
|
+
} else {
|
|
47
|
+
basePath = process.env.MRT_ENV_BASE_PATH || '';
|
|
45
48
|
}
|
|
46
49
|
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
.replace(/\/+/g, '/') // Normalize multiple slashes
|
|
50
|
-
.replace(/\/$/, ''); // Remove trailing slash
|
|
51
|
-
|
|
52
|
-
// Return empty string for root path or empty result
|
|
53
|
-
if (basePath === '/' || !basePath) {
|
|
50
|
+
// Return empty string if no base path is set
|
|
51
|
+
if (!basePath) {
|
|
54
52
|
return '';
|
|
55
53
|
}
|
|
56
54
|
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
// MRT will throw an error on bundle upload if the base path does not match
|
|
56
|
+
// the following regex: /^\/[a-zA-Z0-9_.+$~"'@:-]{1,63}$/
|
|
57
|
+
// This validates:
|
|
58
|
+
// - Starts with /
|
|
59
|
+
// - Followed by 1-63 characters (letters, numbers, and special chars: - _ . + $ ~ " ' @ :)
|
|
60
|
+
// - No additional slashes (multi-part paths not allowed, no trailing slashes)
|
|
61
|
+
// - No spaces
|
|
62
|
+
// - Total max length of 64 characters (1 slash + 63 chars)
|
|
63
|
+
if (!/^\/[a-zA-Z0-9_.+$~"'@:-]{1,63}$/.test(basePath)) {
|
|
64
|
+
throw new Error("Invalid envBasePath configuration. Base path must start with '/' followed by 1-63 characters. Only letters, numbers, and the following special characters are allowed: - _ . + $ ~ \" ' @ :");
|
|
64
65
|
}
|
|
65
66
|
return basePath;
|
|
66
67
|
};
|
|
@@ -1,55 +1,98 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _ssrNamespacePaths = require("./ssr-namespace-paths");
|
|
4
|
-
var
|
|
5
|
-
function
|
|
6
|
-
|
|
4
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
5
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
6
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
7
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
8
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } /*
|
|
7
9
|
* Copyright (c) 2024, Salesforce, Inc.
|
|
8
10
|
* All rights reserved.
|
|
9
11
|
* SPDX-License-Identifier: BSD-3-Clause
|
|
10
12
|
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
11
13
|
*/
|
|
12
|
-
|
|
13
|
-
jest.mock('./ssr-config');
|
|
14
14
|
describe('ssr-namespace-paths tests', () => {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
});
|
|
19
|
-
|
|
15
|
+
const originalEnv = process.env;
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
jest.resetModules();
|
|
18
|
+
process.env = _objectSpread({}, originalEnv);
|
|
19
|
+
delete process.env.MRT_ENV_BASE_PATH;
|
|
20
|
+
// Ensure we're in Node environment (no window)
|
|
21
|
+
delete global.window;
|
|
20
22
|
});
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
process.env = originalEnv;
|
|
25
|
+
delete global.window;
|
|
24
26
|
});
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
describe('Node environment (process.env)', () => {
|
|
28
|
+
test('getEnvBasePath returns base path from environment variable', () => {
|
|
29
|
+
process.env.MRT_ENV_BASE_PATH = '/sample';
|
|
30
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/sample');
|
|
28
31
|
});
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
test('getEnvBasePath removes trailing slash', () => {
|
|
32
|
-
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
33
|
-
envBasePath: '/sample/'
|
|
32
|
+
test('getEnvBasePath returns empty string if no base path is set', () => {
|
|
33
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('');
|
|
34
34
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
jest.spyOn(ssrConfig, 'getConfig').mockReturnValue({
|
|
39
|
-
envBasePath: '/sample.*'
|
|
35
|
+
test('getEnvBasePath throws error for base path with trailing slash', () => {
|
|
36
|
+
process.env.MRT_ENV_BASE_PATH = '/sample/';
|
|
37
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
40
38
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
39
|
+
test('getEnvBasePath throws error for just a slash', () => {
|
|
40
|
+
process.env.MRT_ENV_BASE_PATH = '/';
|
|
41
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
42
|
+
});
|
|
43
|
+
test('getEnvBasePath throws error if invalid characters are detected in envBasePath', () => {
|
|
44
|
+
process.env.MRT_ENV_BASE_PATH = '/sample<script>';
|
|
45
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
46
|
+
});
|
|
47
|
+
test('getEnvBasePath throws error for envBasePath with whitespace', () => {
|
|
48
|
+
process.env.MRT_ENV_BASE_PATH = ' /sample ';
|
|
49
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
50
|
+
});
|
|
51
|
+
test('getEnvBasePath throws error for multi-part base paths with slashes', () => {
|
|
52
|
+
process.env.MRT_ENV_BASE_PATH = '/test/sample';
|
|
53
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
54
|
+
});
|
|
55
|
+
test('getEnvBasePath allows special characters: . + $ ~ " \' @ : -', () => {
|
|
56
|
+
process.env.MRT_ENV_BASE_PATH = '/a.b+c$d~e"f\'g@h:i-j_k';
|
|
57
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/a.b+c$d~e"f\'g@h:i-j_k');
|
|
58
|
+
});
|
|
59
|
+
test('getEnvBasePath throws error if base path exceeds 64 characters', () => {
|
|
60
|
+
// 65 characters total (1 slash + 64 chars)
|
|
61
|
+
process.env.MRT_ENV_BASE_PATH = '/' + 'a'.repeat(64);
|
|
62
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
63
|
+
});
|
|
64
|
+
test('getEnvBasePath allows base path of exactly 64 characters', () => {
|
|
65
|
+
// 64 characters total (1 slash + 63 chars)
|
|
66
|
+
process.env.MRT_ENV_BASE_PATH = '/' + 'a'.repeat(63);
|
|
67
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/' + 'a'.repeat(63));
|
|
46
68
|
});
|
|
47
|
-
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/sample');
|
|
48
69
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
70
|
+
describe('Browser environment (window)', () => {
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
global.window = {};
|
|
73
|
+
});
|
|
74
|
+
test('getEnvBasePath returns base path from window global', () => {
|
|
75
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/sample';
|
|
76
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/sample');
|
|
77
|
+
});
|
|
78
|
+
test('getEnvBasePath returns empty string if window global is not set', () => {
|
|
79
|
+
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('');
|
|
80
|
+
});
|
|
81
|
+
test('getEnvBasePath throws error for base path with trailing slash from window global', () => {
|
|
82
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/sample/';
|
|
83
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
84
|
+
});
|
|
85
|
+
test('getEnvBasePath throws error for window global value with whitespace', () => {
|
|
86
|
+
global.window.__MRT_ENV_BASE_PATH__ = ' /sample ';
|
|
87
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
88
|
+
});
|
|
89
|
+
test('getEnvBasePath throws error if invalid characters in window global', () => {
|
|
90
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/sample<script>';
|
|
91
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
92
|
+
});
|
|
93
|
+
test('getEnvBasePath throws error for multi-part base paths in window global', () => {
|
|
94
|
+
global.window.__MRT_ENV_BASE_PATH__ = '/test/sample';
|
|
95
|
+
expect(() => (0, _ssrNamespacePaths.getEnvBasePath)()).toThrow('Invalid envBasePath configuration');
|
|
52
96
|
});
|
|
53
|
-
expect((0, _ssrNamespacePaths.getEnvBasePath)()).toBe('/test/sample');
|
|
54
97
|
});
|
|
55
98
|
});
|