@pwrdrvr/microapps-router-lib 1.2.0-beta.7 → 1.2.0-beta.8
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 +5 -4
- package/src/app-cache.spec.ts +0 -175
- package/src/get-app-info.spec.ts +0 -77
- package/src/get-route.prefix.spec.ts +0 -93
- package/src/get-route.spec.ts +0 -585
- package/src/load-app-frame.spec.ts +0 -51
- package/src/normalize-path-prefix.spec.ts +0 -27
- package/src/redirect-default-file.spec.ts +0 -98
- package/src/route-app.spec.ts +0 -128
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pwrdrvr/microapps-router-lib",
|
|
3
|
-
"version": "1.2.0-beta.
|
|
3
|
+
"version": "1.2.0-beta.8",
|
|
4
4
|
"description": "Router library for the microapps framework",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,15 +15,15 @@
|
|
|
15
15
|
},
|
|
16
16
|
"homepage": "https://github.com/pwrdrvr/microapps-core#readme",
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@aws-sdk/client-dynamodb": "^3.
|
|
18
|
+
"@aws-sdk/client-dynamodb": "^3.1024.0",
|
|
19
19
|
"fs-extra": "^9.0.0",
|
|
20
20
|
"lambda-log": "^3.0.0",
|
|
21
21
|
"source-map-support": "^0.5.0",
|
|
22
22
|
"tslib": "^2.1.0",
|
|
23
|
-
"@pwrdrvr/microapps-datalib": "1.2.0-beta.
|
|
23
|
+
"@pwrdrvr/microapps-datalib": "1.2.0-beta.8"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@aws-sdk/client-dynamodb": "3.
|
|
26
|
+
"@aws-sdk/client-dynamodb": "3.1024.0",
|
|
27
27
|
"@types/aws-lambda": "8.10.110",
|
|
28
28
|
"@types/fs-extra": "^9.0.13",
|
|
29
29
|
"@types/lambda-log": "^2.2.0",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"files": [
|
|
42
42
|
"dist",
|
|
43
43
|
"src",
|
|
44
|
+
"!src/**/*.spec.ts",
|
|
44
45
|
"package.json",
|
|
45
46
|
"LICENSE"
|
|
46
47
|
],
|
package/src/app-cache.spec.ts
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
import 'jest-dynalite/withDb';
|
|
3
|
-
import * as dynamodb from '@aws-sdk/client-dynamodb';
|
|
4
|
-
import { Application, DBManager, Version, Rules } from '@pwrdrvr/microapps-datalib';
|
|
5
|
-
import { AppVersionCache } from './app-cache';
|
|
6
|
-
|
|
7
|
-
let dynamoClient: dynamodb.DynamoDBClient;
|
|
8
|
-
let dbManager: DBManager;
|
|
9
|
-
|
|
10
|
-
const TEST_TABLE_NAME = 'microapps';
|
|
11
|
-
|
|
12
|
-
describe('app-cache', () => {
|
|
13
|
-
beforeAll(() => {
|
|
14
|
-
jest.setTimeout(30000);
|
|
15
|
-
|
|
16
|
-
dynamoClient = new dynamodb.DynamoDBClient({
|
|
17
|
-
endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
|
|
18
|
-
tls: false,
|
|
19
|
-
region: 'local',
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
// Init the DB manager to point it at the right table
|
|
23
|
-
dbManager = new DBManager({ dynamoClient, tableName: TEST_TABLE_NAME });
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
describe('GetRules', () => {
|
|
27
|
-
it('Returns cached record after deleted from DB', async () => {
|
|
28
|
-
const app = new Application({
|
|
29
|
-
AppName: 'Cached',
|
|
30
|
-
DisplayName: 'Cached App',
|
|
31
|
-
});
|
|
32
|
-
await app.Save(dbManager);
|
|
33
|
-
|
|
34
|
-
const version = new Version({
|
|
35
|
-
AppName: 'Cached',
|
|
36
|
-
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:cached',
|
|
37
|
-
URL: 'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
38
|
-
SemVer: '3.2.1-beta.1',
|
|
39
|
-
Status: 'deployed',
|
|
40
|
-
Type: 'lambda',
|
|
41
|
-
});
|
|
42
|
-
await version.Save(dbManager);
|
|
43
|
-
|
|
44
|
-
const rules = new Rules({
|
|
45
|
-
AppName: 'Cached',
|
|
46
|
-
Version: 0,
|
|
47
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
48
|
-
});
|
|
49
|
-
await rules.Save(dbManager);
|
|
50
|
-
|
|
51
|
-
const appVersionCache = new AppVersionCache({ dbManager });
|
|
52
|
-
|
|
53
|
-
// Seed the cache while record exists
|
|
54
|
-
const versionWhenDBExists = await appVersionCache.GetRules({
|
|
55
|
-
key: { AppName: 'Cached' },
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
expect(versionWhenDBExists).toHaveProperty('AppName', 'cached');
|
|
59
|
-
expect(versionWhenDBExists).toHaveProperty('RuleSet', {
|
|
60
|
-
default: { AttributeName: '', AttributeValue: '', SemVer: '3.2.1-beta.1' },
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
// Clobber the Rules record
|
|
64
|
-
await Application.UpdateDefaultRule({
|
|
65
|
-
dbManager,
|
|
66
|
-
key: { AppName: 'Cached', SemVer: '9.9.9' },
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// Get record from cache after DB record is deleted
|
|
70
|
-
const rulesWhenCleared = await appVersionCache.GetRules({
|
|
71
|
-
key: { AppName: 'Cached' },
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
expect(rulesWhenCleared).toEqual(versionWhenDBExists);
|
|
75
|
-
});
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
describe('GetVersionInfo', () => {
|
|
79
|
-
it('Returns cached record after deleted from DB', async () => {
|
|
80
|
-
const app = new Application({
|
|
81
|
-
AppName: 'Cached',
|
|
82
|
-
DisplayName: 'Cached App',
|
|
83
|
-
});
|
|
84
|
-
await app.Save(dbManager);
|
|
85
|
-
|
|
86
|
-
const version = new Version({
|
|
87
|
-
AppName: 'Cached',
|
|
88
|
-
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:cached',
|
|
89
|
-
URL: 'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
90
|
-
SemVer: '3.2.1-beta.1',
|
|
91
|
-
Status: 'deployed',
|
|
92
|
-
Type: 'lambda',
|
|
93
|
-
});
|
|
94
|
-
await version.Save(dbManager);
|
|
95
|
-
|
|
96
|
-
const rules = new Rules({
|
|
97
|
-
AppName: 'Cached',
|
|
98
|
-
Version: 0,
|
|
99
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
100
|
-
});
|
|
101
|
-
await rules.Save(dbManager);
|
|
102
|
-
|
|
103
|
-
const appVersionCache = new AppVersionCache({ dbManager });
|
|
104
|
-
|
|
105
|
-
// Seed the cache while record exists
|
|
106
|
-
const versionWhenDBExists = await appVersionCache.GetVersionInfo({
|
|
107
|
-
key: { AppName: 'Cached', SemVer: '3.2.1-beta.1' },
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
expect(versionWhenDBExists).toHaveProperty('AppName', 'cached');
|
|
111
|
-
expect(versionWhenDBExists).toHaveProperty(
|
|
112
|
-
'URL',
|
|
113
|
-
'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
114
|
-
);
|
|
115
|
-
expect(versionWhenDBExists).toHaveProperty('SemVer', '3.2.1-beta.1');
|
|
116
|
-
expect(versionWhenDBExists).toHaveProperty('Status', 'deployed');
|
|
117
|
-
expect(versionWhenDBExists).toHaveProperty('Type', 'lambda');
|
|
118
|
-
|
|
119
|
-
// Delete the record
|
|
120
|
-
await Version.DeleteVersion({
|
|
121
|
-
dbManager,
|
|
122
|
-
key: { AppName: 'Cached', SemVer: '3.2.1-beta.1' },
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
// Get record from cache after DB record is deleted
|
|
126
|
-
const versionWhenDBCleared = await appVersionCache.GetVersionInfo({
|
|
127
|
-
key: { AppName: 'Cached', SemVer: '3.2.1-beta.1' },
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
expect(versionWhenDBCleared).toEqual(versionWhenDBExists);
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('Negative Cache', async () => {
|
|
134
|
-
const appVersionCache = new AppVersionCache({ dbManager });
|
|
135
|
-
|
|
136
|
-
// Seed the negative cache
|
|
137
|
-
const versionWhenDBExists = await appVersionCache.GetVersionInfo({
|
|
138
|
-
key: { AppName: 'Missing', SemVer: '7.6.8' },
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
// Confirm record is not in the DB
|
|
142
|
-
expect(versionWhenDBExists).toBeUndefined();
|
|
143
|
-
|
|
144
|
-
const app = new Application({
|
|
145
|
-
AppName: 'Missing',
|
|
146
|
-
DisplayName: 'Bat App',
|
|
147
|
-
});
|
|
148
|
-
await app.Save(dbManager);
|
|
149
|
-
|
|
150
|
-
const version = new Version({
|
|
151
|
-
AppName: 'Missing',
|
|
152
|
-
SemVer: '7.6.8',
|
|
153
|
-
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:bat',
|
|
154
|
-
URL: 'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
155
|
-
Status: 'deployed',
|
|
156
|
-
Type: 'lambda',
|
|
157
|
-
});
|
|
158
|
-
await version.Save(dbManager);
|
|
159
|
-
|
|
160
|
-
const rules = new Rules({
|
|
161
|
-
AppName: 'Missing',
|
|
162
|
-
Version: 0,
|
|
163
|
-
RuleSet: { default: { SemVer: '7.6.8', AttributeName: '', AttributeValue: '' } },
|
|
164
|
-
});
|
|
165
|
-
await rules.Save(dbManager);
|
|
166
|
-
|
|
167
|
-
// Get record from cache after DB record is created - should be hidden by negative cache
|
|
168
|
-
const versionWhenDBCreated = await appVersionCache.GetVersionInfo({
|
|
169
|
-
key: { AppName: 'Missing', SemVer: '7.6.8' },
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
expect(versionWhenDBCreated).toBeUndefined();
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
});
|
package/src/get-app-info.spec.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { DBManager, Rules } from '@pwrdrvr/microapps-datalib';
|
|
2
|
-
import { AppVersionCache } from './app-cache';
|
|
3
|
-
import { GetAppInfo } from './get-app-info';
|
|
4
|
-
|
|
5
|
-
jest.mock('@pwrdrvr/microapps-datalib');
|
|
6
|
-
|
|
7
|
-
describe('GetAppInfo', () => {
|
|
8
|
-
const dbManager = {} as DBManager;
|
|
9
|
-
const getAppVersionCacheSpy = jest.spyOn(AppVersionCache, 'GetInstance');
|
|
10
|
-
|
|
11
|
-
beforeEach(() => {
|
|
12
|
-
jest.clearAllMocks();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
afterEach(() => {
|
|
16
|
-
getAppVersionCacheSpy.mockReset();
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const testCases = [
|
|
20
|
-
{
|
|
21
|
-
caseName: 'returns the correct app name when it exists',
|
|
22
|
-
appName: 'testApp',
|
|
23
|
-
mockRules: {
|
|
24
|
-
AppName: 'testapp',
|
|
25
|
-
Version: 1,
|
|
26
|
-
RuleSet: {
|
|
27
|
-
default: {
|
|
28
|
-
AttributeName: 'default',
|
|
29
|
-
AttributeValue: '',
|
|
30
|
-
SemVer: '1.0.0',
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
} as unknown as Rules,
|
|
34
|
-
expected: 'testApp',
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
caseName:
|
|
38
|
-
'returns undefined when the app name does not exist and there is no [root] catch-all app',
|
|
39
|
-
appName: 'nonexistent',
|
|
40
|
-
mockRules: undefined,
|
|
41
|
-
expected: undefined,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
caseName:
|
|
45
|
-
'returns [root] when the app name does not exist but there is a [root] catch-all app',
|
|
46
|
-
appName: 'nonexistent',
|
|
47
|
-
mockRules: {
|
|
48
|
-
AppName: '[root]',
|
|
49
|
-
RuleSet: {
|
|
50
|
-
default: {
|
|
51
|
-
AttributeName: 'default',
|
|
52
|
-
AttributeValue: '',
|
|
53
|
-
SemVer: '9.0.0',
|
|
54
|
-
},
|
|
55
|
-
} as unknown as Rules,
|
|
56
|
-
},
|
|
57
|
-
expected: '[root]',
|
|
58
|
-
},
|
|
59
|
-
];
|
|
60
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
61
|
-
it.each(testCases)('$caseName', async ({ caseName, appName, mockRules, expected }) => {
|
|
62
|
-
getAppVersionCacheSpy.mockImplementation(() => {
|
|
63
|
-
return {
|
|
64
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
65
|
-
GetRules: async ({ key }: { key: { AppName: string } }) => {
|
|
66
|
-
if (key.AppName === appName || key.AppName === '[root]') {
|
|
67
|
-
return mockRules;
|
|
68
|
-
}
|
|
69
|
-
return undefined;
|
|
70
|
-
},
|
|
71
|
-
} as unknown as AppVersionCache;
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const result = await GetAppInfo({ dbManager, appName });
|
|
75
|
-
expect(result).toEqual(expected);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
import 'reflect-metadata';
|
|
3
|
-
import 'jest-dynalite/withDb';
|
|
4
|
-
import * as dynamodb from '@aws-sdk/client-dynamodb';
|
|
5
|
-
import { Application, DBManager, Version, Rules } from '@pwrdrvr/microapps-datalib';
|
|
6
|
-
import { GetRoute } from './index';
|
|
7
|
-
|
|
8
|
-
let dynamoClient: dynamodb.DynamoDBClient;
|
|
9
|
-
let dbManager: DBManager;
|
|
10
|
-
|
|
11
|
-
const TEST_TABLE_NAME = 'microapps';
|
|
12
|
-
|
|
13
|
-
describe('router - with prefix', () => {
|
|
14
|
-
beforeAll(() => {
|
|
15
|
-
dynamoClient = new dynamodb.DynamoDBClient({
|
|
16
|
-
endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
|
|
17
|
-
tls: false,
|
|
18
|
-
region: 'local',
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
// Init the DB manager to point it at the right table
|
|
22
|
-
dbManager = new DBManager({ dynamoClient, tableName: TEST_TABLE_NAME });
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it('should serve appframe with version and default file substitued', async () => {
|
|
26
|
-
const app = new Application({
|
|
27
|
-
AppName: 'Bat',
|
|
28
|
-
DisplayName: 'Bat App',
|
|
29
|
-
});
|
|
30
|
-
await app.Save(dbManager);
|
|
31
|
-
|
|
32
|
-
const version = new Version({
|
|
33
|
-
AppName: 'Bat',
|
|
34
|
-
DefaultFile: 'bat.html',
|
|
35
|
-
IntegrationID: 'abcd',
|
|
36
|
-
SemVer: '3.2.1-beta.1',
|
|
37
|
-
Status: 'deployed',
|
|
38
|
-
Type: 'lambda',
|
|
39
|
-
});
|
|
40
|
-
await version.Save(dbManager);
|
|
41
|
-
|
|
42
|
-
const rules = new Rules({
|
|
43
|
-
AppName: 'Bat',
|
|
44
|
-
Version: 0,
|
|
45
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
46
|
-
});
|
|
47
|
-
await rules.Save(dbManager);
|
|
48
|
-
|
|
49
|
-
// Call the handler
|
|
50
|
-
const response = await GetRoute({
|
|
51
|
-
dbManager,
|
|
52
|
-
normalizedPathPrefix: '/qa',
|
|
53
|
-
rawPath: '/qa/bat/',
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
expect(response).toHaveProperty('statusCode');
|
|
57
|
-
expect(response.statusCode).toBe(200);
|
|
58
|
-
expect(response).toBeDefined();
|
|
59
|
-
expect(response.iFrameAppVersionPath).toBe('/qa/bat/3.2.1-beta.1/bat.html');
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should 404 appframe with version if the prefix is missing', async () => {
|
|
63
|
-
const app = new Application({
|
|
64
|
-
AppName: 'Bat',
|
|
65
|
-
DisplayName: 'Bat App',
|
|
66
|
-
});
|
|
67
|
-
await app.Save(dbManager);
|
|
68
|
-
|
|
69
|
-
const version = new Version({
|
|
70
|
-
AppName: 'Bat',
|
|
71
|
-
DefaultFile: 'bat.html',
|
|
72
|
-
IntegrationID: 'abcd',
|
|
73
|
-
SemVer: '3.2.1-beta.1',
|
|
74
|
-
Status: 'deployed',
|
|
75
|
-
Type: 'lambda',
|
|
76
|
-
});
|
|
77
|
-
await version.Save(dbManager);
|
|
78
|
-
|
|
79
|
-
const rules = new Rules({
|
|
80
|
-
AppName: 'Bat',
|
|
81
|
-
Version: 0,
|
|
82
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
83
|
-
});
|
|
84
|
-
await rules.Save(dbManager);
|
|
85
|
-
|
|
86
|
-
// Call the handler
|
|
87
|
-
const response = await GetRoute({ dbManager, normalizedPathPrefix: '/qa', rawPath: '/bat/' });
|
|
88
|
-
|
|
89
|
-
expect(response).toHaveProperty('statusCode');
|
|
90
|
-
expect(response.statusCode).toBe(404);
|
|
91
|
-
expect(response.errorMessage).toBe('Request not routable');
|
|
92
|
-
});
|
|
93
|
-
});
|
package/src/get-route.spec.ts
DELETED
|
@@ -1,585 +0,0 @@
|
|
|
1
|
-
/// <reference types="jest" />
|
|
2
|
-
import 'jest-dynalite/withDb';
|
|
3
|
-
import * as dynamodb from '@aws-sdk/client-dynamodb';
|
|
4
|
-
import { Application, DBManager, Version, Rules } from '@pwrdrvr/microapps-datalib';
|
|
5
|
-
import { GetRoute } from './index';
|
|
6
|
-
|
|
7
|
-
let dynamoClient: dynamodb.DynamoDBClient;
|
|
8
|
-
let dbManager: DBManager;
|
|
9
|
-
|
|
10
|
-
const TEST_TABLE_NAME = 'microapps';
|
|
11
|
-
|
|
12
|
-
describe('router - without prefix', () => {
|
|
13
|
-
beforeAll(() => {
|
|
14
|
-
dynamoClient = new dynamodb.DynamoDBClient({
|
|
15
|
-
endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
|
|
16
|
-
tls: false,
|
|
17
|
-
region: 'local',
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// Init the DB manager to point it at the right table
|
|
21
|
-
dbManager = new DBManager({ dynamoClient, tableName: TEST_TABLE_NAME });
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
describe('StartupType: iframe', () => {
|
|
25
|
-
it('should serve appframe with version and default file substitued', async () => {
|
|
26
|
-
const app = new Application({
|
|
27
|
-
AppName: 'Bat',
|
|
28
|
-
DisplayName: 'Bat App',
|
|
29
|
-
});
|
|
30
|
-
await app.Save(dbManager);
|
|
31
|
-
|
|
32
|
-
const version = new Version({
|
|
33
|
-
AppName: 'Bat',
|
|
34
|
-
DefaultFile: 'bat.html',
|
|
35
|
-
IntegrationID: 'abcd',
|
|
36
|
-
SemVer: '3.2.1-beta.1',
|
|
37
|
-
Status: 'deployed',
|
|
38
|
-
Type: 'lambda',
|
|
39
|
-
});
|
|
40
|
-
await version.Save(dbManager);
|
|
41
|
-
|
|
42
|
-
const rules = new Rules({
|
|
43
|
-
AppName: 'Bat',
|
|
44
|
-
Version: 0,
|
|
45
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
46
|
-
});
|
|
47
|
-
await rules.Save(dbManager);
|
|
48
|
-
|
|
49
|
-
// Call the handler
|
|
50
|
-
const response = await GetRoute({
|
|
51
|
-
dbManager,
|
|
52
|
-
rawPath: '/bat/',
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
expect(response).toHaveProperty('statusCode');
|
|
56
|
-
expect(response.statusCode).toBe(200);
|
|
57
|
-
expect(response).toBeDefined();
|
|
58
|
-
expect(response.iFrameAppVersionPath).toBe('/bat/3.2.1-beta.1/bat.html');
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
it('should serve appframe with appver query string and default file substitued', async () => {
|
|
62
|
-
const AppName = 'BatAppVer';
|
|
63
|
-
const app = new Application({
|
|
64
|
-
AppName,
|
|
65
|
-
DisplayName: 'Bat App',
|
|
66
|
-
});
|
|
67
|
-
await app.Save(dbManager);
|
|
68
|
-
|
|
69
|
-
const version = new Version({
|
|
70
|
-
AppName,
|
|
71
|
-
DefaultFile: 'bat.html',
|
|
72
|
-
IntegrationID: 'abcd',
|
|
73
|
-
SemVer: '3.2.1-beta.1',
|
|
74
|
-
Status: 'deployed',
|
|
75
|
-
Type: 'lambda',
|
|
76
|
-
});
|
|
77
|
-
await version.Save(dbManager);
|
|
78
|
-
const version2 = new Version({
|
|
79
|
-
AppName,
|
|
80
|
-
DefaultFile: 'bat.html',
|
|
81
|
-
IntegrationID: 'abcd',
|
|
82
|
-
SemVer: '3.2.1-beta.2',
|
|
83
|
-
Status: 'deployed',
|
|
84
|
-
Type: 'lambda',
|
|
85
|
-
});
|
|
86
|
-
await version2.Save(dbManager);
|
|
87
|
-
|
|
88
|
-
const rules = new Rules({
|
|
89
|
-
AppName,
|
|
90
|
-
Version: 0,
|
|
91
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
92
|
-
});
|
|
93
|
-
await rules.Save(dbManager);
|
|
94
|
-
|
|
95
|
-
// Call the handler
|
|
96
|
-
const response = await GetRoute({
|
|
97
|
-
dbManager,
|
|
98
|
-
rawPath: '/batappver/',
|
|
99
|
-
queryStringParameters: new URLSearchParams('appver=3.2.1-beta.2'),
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
expect(response).toHaveProperty('statusCode');
|
|
103
|
-
expect(response.statusCode).toBe(200);
|
|
104
|
-
expect(response).toBeDefined();
|
|
105
|
-
expect(response.iFrameAppVersionPath).toBe('/batappver/3.2.1-beta.2/bat.html');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
it('static app - request to app/x.y.z should redirect to defaultFile', async () => {
|
|
109
|
-
const app = new Application({
|
|
110
|
-
AppName: 'Bat',
|
|
111
|
-
DisplayName: 'Bat App',
|
|
112
|
-
});
|
|
113
|
-
await app.Save(dbManager);
|
|
114
|
-
|
|
115
|
-
const version = new Version({
|
|
116
|
-
AppName: 'Bat',
|
|
117
|
-
DefaultFile: 'bat.html',
|
|
118
|
-
IntegrationID: 'abcd',
|
|
119
|
-
SemVer: '3.2.1-beta.1',
|
|
120
|
-
Status: 'deployed',
|
|
121
|
-
Type: 'static',
|
|
122
|
-
StartupType: 'iframe',
|
|
123
|
-
});
|
|
124
|
-
await version.Save(dbManager);
|
|
125
|
-
|
|
126
|
-
const rules = new Rules({
|
|
127
|
-
AppName: 'Bat',
|
|
128
|
-
Version: 0,
|
|
129
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
130
|
-
});
|
|
131
|
-
await rules.Save(dbManager);
|
|
132
|
-
|
|
133
|
-
// Call the handler
|
|
134
|
-
const response = await GetRoute({ dbManager, rawPath: '/bat/3.2.1-beta.1' });
|
|
135
|
-
|
|
136
|
-
expect(response).toHaveProperty('statusCode');
|
|
137
|
-
expect(response.statusCode).toBe(302);
|
|
138
|
-
expect(response.redirectLocation).toBeDefined();
|
|
139
|
-
expect(response.redirectLocation).toBe('/bat/3.2.1-beta.1/bat.html');
|
|
140
|
-
}, 60000);
|
|
141
|
-
|
|
142
|
-
it('static app - request to app/x.y.z/ should not redirect if no defaultFile', async () => {
|
|
143
|
-
const app = new Application({
|
|
144
|
-
AppName: 'Bat',
|
|
145
|
-
DisplayName: 'Bat App',
|
|
146
|
-
});
|
|
147
|
-
await app.Save(dbManager);
|
|
148
|
-
|
|
149
|
-
const version = new Version({
|
|
150
|
-
AppName: 'Bat',
|
|
151
|
-
IntegrationID: 'abcd',
|
|
152
|
-
SemVer: '3.2.1-beta.2',
|
|
153
|
-
Status: 'deployed',
|
|
154
|
-
Type: 'static',
|
|
155
|
-
StartupType: 'iframe',
|
|
156
|
-
});
|
|
157
|
-
await version.Save(dbManager);
|
|
158
|
-
|
|
159
|
-
const rules = new Rules({
|
|
160
|
-
AppName: 'Bat',
|
|
161
|
-
Version: 0,
|
|
162
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.2', AttributeName: '', AttributeValue: '' } },
|
|
163
|
-
});
|
|
164
|
-
await rules.Save(dbManager);
|
|
165
|
-
|
|
166
|
-
// Call the handler
|
|
167
|
-
const response = await GetRoute({ dbManager, rawPath: '/bat/3.2.1-beta.2/' });
|
|
168
|
-
|
|
169
|
-
expect(response).toHaveProperty('appName');
|
|
170
|
-
expect(response.appName).toBe('bat');
|
|
171
|
-
expect(response).toHaveProperty('semVer');
|
|
172
|
-
expect(response.semVer).toBe('3.2.1-beta.2');
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('static app - request to app/some.html should create iframe with path after version', async () => {
|
|
176
|
-
const app = new Application({
|
|
177
|
-
AppName: 'Bat',
|
|
178
|
-
DisplayName: 'Bat App',
|
|
179
|
-
});
|
|
180
|
-
await app.Save(dbManager);
|
|
181
|
-
|
|
182
|
-
const version = new Version({
|
|
183
|
-
AppName: 'Bat',
|
|
184
|
-
DefaultFile: 'bat.html',
|
|
185
|
-
IntegrationID: 'abcd',
|
|
186
|
-
SemVer: '3.2.1-beta.1',
|
|
187
|
-
Status: 'deployed',
|
|
188
|
-
Type: 'static',
|
|
189
|
-
StartupType: 'iframe',
|
|
190
|
-
});
|
|
191
|
-
await version.Save(dbManager);
|
|
192
|
-
|
|
193
|
-
const rules = new Rules({
|
|
194
|
-
AppName: 'Bat',
|
|
195
|
-
Version: 0,
|
|
196
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
197
|
-
});
|
|
198
|
-
await rules.Save(dbManager);
|
|
199
|
-
|
|
200
|
-
// Call the handler
|
|
201
|
-
const response = await GetRoute({ dbManager, rawPath: '/bat/some.html' });
|
|
202
|
-
|
|
203
|
-
expect(response).toHaveProperty('statusCode');
|
|
204
|
-
expect(response.statusCode).toBe(200);
|
|
205
|
-
expect(response.redirectLocation).not.toBeDefined();
|
|
206
|
-
expect(response.iFrameAppVersionPath).toBe('/bat/3.2.1-beta.1/some.html');
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('static app - request to app/x.y.z/ should redirect to defaultFile', async () => {
|
|
210
|
-
const app = new Application({
|
|
211
|
-
AppName: 'Bat',
|
|
212
|
-
DisplayName: 'Bat App',
|
|
213
|
-
});
|
|
214
|
-
await app.Save(dbManager);
|
|
215
|
-
|
|
216
|
-
const version = new Version({
|
|
217
|
-
AppName: 'Bat',
|
|
218
|
-
DefaultFile: 'bat.html',
|
|
219
|
-
IntegrationID: 'abcd',
|
|
220
|
-
SemVer: '3.2.1-beta.1',
|
|
221
|
-
Status: 'deployed',
|
|
222
|
-
Type: 'static',
|
|
223
|
-
StartupType: 'iframe',
|
|
224
|
-
});
|
|
225
|
-
await version.Save(dbManager);
|
|
226
|
-
|
|
227
|
-
const rules = new Rules({
|
|
228
|
-
AppName: 'Bat',
|
|
229
|
-
Version: 0,
|
|
230
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
231
|
-
});
|
|
232
|
-
await rules.Save(dbManager);
|
|
233
|
-
|
|
234
|
-
// Call the handler
|
|
235
|
-
const response = await GetRoute({ dbManager, rawPath: '/bat/3.2.1-beta.1/' });
|
|
236
|
-
|
|
237
|
-
expect(response).toHaveProperty('statusCode');
|
|
238
|
-
expect(response.statusCode).toBe(302);
|
|
239
|
-
expect(response.redirectLocation).toBeDefined();
|
|
240
|
-
expect(response.redirectLocation).toBe('/bat/3.2.1-beta.1/bat.html');
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('static app - request to app/notVersion should load app frame with /notVersion suffix', async () => {
|
|
244
|
-
const AppName = 'Bat123';
|
|
245
|
-
const app = new Application({
|
|
246
|
-
AppName,
|
|
247
|
-
DisplayName: 'Bat App',
|
|
248
|
-
});
|
|
249
|
-
await app.Save(dbManager);
|
|
250
|
-
|
|
251
|
-
const version = new Version({
|
|
252
|
-
AppName,
|
|
253
|
-
DefaultFile: 'bat.html',
|
|
254
|
-
IntegrationID: 'abcd',
|
|
255
|
-
SemVer: '3.2.1-beta.1',
|
|
256
|
-
Status: 'deployed',
|
|
257
|
-
Type: 'static',
|
|
258
|
-
StartupType: 'iframe',
|
|
259
|
-
});
|
|
260
|
-
await version.Save(dbManager);
|
|
261
|
-
|
|
262
|
-
const rules = new Rules({
|
|
263
|
-
AppName,
|
|
264
|
-
Version: 0,
|
|
265
|
-
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
266
|
-
});
|
|
267
|
-
await rules.Save(dbManager);
|
|
268
|
-
|
|
269
|
-
// Call the handler
|
|
270
|
-
const response = await GetRoute({ dbManager, rawPath: `/${AppName}/notVersion` });
|
|
271
|
-
|
|
272
|
-
expect(response).toHaveProperty('statusCode');
|
|
273
|
-
expect(response.statusCode).toBe(200);
|
|
274
|
-
expect(response).toBeDefined();
|
|
275
|
-
expect(response.iFrameAppVersionPath).toBe(`/${AppName}/3.2.1-beta.1/notVersion`);
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
it('should serve appframe with no default file', async () => {
|
|
279
|
-
const AppName = 'Bat124';
|
|
280
|
-
const app = new Application({
|
|
281
|
-
AppName,
|
|
282
|
-
DisplayName: 'Bat App',
|
|
283
|
-
});
|
|
284
|
-
await app.Save(dbManager);
|
|
285
|
-
|
|
286
|
-
const version = new Version({
|
|
287
|
-
AppName,
|
|
288
|
-
DefaultFile: '',
|
|
289
|
-
IntegrationID: 'abcd',
|
|
290
|
-
SemVer: '3.2.1-beta1',
|
|
291
|
-
Status: 'deployed',
|
|
292
|
-
Type: 'lambda',
|
|
293
|
-
StartupType: 'iframe',
|
|
294
|
-
});
|
|
295
|
-
await version.Save(dbManager);
|
|
296
|
-
|
|
297
|
-
const rules = new Rules({
|
|
298
|
-
AppName,
|
|
299
|
-
Version: 0,
|
|
300
|
-
RuleSet: { default: { SemVer: '3.2.1-beta1', AttributeName: '', AttributeValue: '' } },
|
|
301
|
-
});
|
|
302
|
-
await rules.Save(dbManager);
|
|
303
|
-
|
|
304
|
-
// Call the handler
|
|
305
|
-
const response = await GetRoute({ dbManager, rawPath: `/${AppName}/` });
|
|
306
|
-
|
|
307
|
-
expect(response).toBeDefined();
|
|
308
|
-
expect(response).toHaveProperty('statusCode');
|
|
309
|
-
expect(response.statusCode).toBe(200);
|
|
310
|
-
expect(response.iFrameAppVersionPath).toBe(`/${AppName}/3.2.1-beta1`);
|
|
311
|
-
});
|
|
312
|
-
|
|
313
|
-
it('should serve appframe with sub-route', async () => {
|
|
314
|
-
const AppName = 'Bat125';
|
|
315
|
-
const app = new Application({
|
|
316
|
-
AppName,
|
|
317
|
-
DisplayName: 'Bat App',
|
|
318
|
-
});
|
|
319
|
-
await app.Save(dbManager);
|
|
320
|
-
|
|
321
|
-
const version = new Version({
|
|
322
|
-
AppName,
|
|
323
|
-
DefaultFile: '',
|
|
324
|
-
IntegrationID: 'abcd',
|
|
325
|
-
SemVer: '3.2.1-beta2',
|
|
326
|
-
Status: 'deployed',
|
|
327
|
-
Type: 'lambda',
|
|
328
|
-
StartupType: 'iframe',
|
|
329
|
-
});
|
|
330
|
-
await version.Save(dbManager);
|
|
331
|
-
|
|
332
|
-
const rules = new Rules({
|
|
333
|
-
AppName,
|
|
334
|
-
Version: 0,
|
|
335
|
-
RuleSet: { default: { SemVer: '3.2.1-beta2', AttributeName: '', AttributeValue: '' } },
|
|
336
|
-
});
|
|
337
|
-
await rules.Save(dbManager);
|
|
338
|
-
|
|
339
|
-
// Call the handler
|
|
340
|
-
const response = await GetRoute({ dbManager, rawPath: `/${AppName}/demo/grid` });
|
|
341
|
-
|
|
342
|
-
expect(response).toBeDefined();
|
|
343
|
-
expect(response).toHaveProperty('statusCode');
|
|
344
|
-
expect(response.statusCode).toBe(200);
|
|
345
|
-
expect(response.iFrameAppVersionPath).toBe(`/${AppName}/3.2.1-beta2/demo/grid`);
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
it('should serve appframe with sub-route', async () => {
|
|
349
|
-
const AppName = 'Bat126';
|
|
350
|
-
const app = new Application({
|
|
351
|
-
AppName,
|
|
352
|
-
DisplayName: 'Bat App',
|
|
353
|
-
});
|
|
354
|
-
await app.Save(dbManager);
|
|
355
|
-
|
|
356
|
-
const version = new Version({
|
|
357
|
-
AppName,
|
|
358
|
-
DefaultFile: 'someFile.html',
|
|
359
|
-
IntegrationID: 'abcd',
|
|
360
|
-
SemVer: '3.2.1-beta3',
|
|
361
|
-
Status: 'deployed',
|
|
362
|
-
Type: 'lambda',
|
|
363
|
-
StartupType: 'iframe',
|
|
364
|
-
});
|
|
365
|
-
await version.Save(dbManager);
|
|
366
|
-
|
|
367
|
-
const rules = new Rules({
|
|
368
|
-
AppName,
|
|
369
|
-
Version: 0,
|
|
370
|
-
RuleSet: { default: { SemVer: '3.2.1-beta3', AttributeName: '', AttributeValue: '' } },
|
|
371
|
-
});
|
|
372
|
-
await rules.Save(dbManager);
|
|
373
|
-
|
|
374
|
-
// Call the handler
|
|
375
|
-
const response = await GetRoute({ dbManager, rawPath: `/${AppName}/demo` });
|
|
376
|
-
|
|
377
|
-
expect(response).toBeDefined();
|
|
378
|
-
expect(response).toHaveProperty('statusCode');
|
|
379
|
-
expect(response.statusCode).toBe(200);
|
|
380
|
-
expect(response.iFrameAppVersionPath).toBe(`/${AppName}/3.2.1-beta3/demo`);
|
|
381
|
-
});
|
|
382
|
-
|
|
383
|
-
it('should return 404 for /favicon.ico', async () => {
|
|
384
|
-
const app = new Application({
|
|
385
|
-
AppName: 'Bat',
|
|
386
|
-
DisplayName: 'Bat App',
|
|
387
|
-
});
|
|
388
|
-
await app.Save(dbManager);
|
|
389
|
-
|
|
390
|
-
const version = new Version({
|
|
391
|
-
AppName: 'Bat',
|
|
392
|
-
DefaultFile: 'someFile.html',
|
|
393
|
-
IntegrationID: 'abcd',
|
|
394
|
-
SemVer: '3.2.1-beta3',
|
|
395
|
-
Status: 'deployed',
|
|
396
|
-
Type: 'lambda',
|
|
397
|
-
StartupType: 'iframe',
|
|
398
|
-
});
|
|
399
|
-
await version.Save(dbManager);
|
|
400
|
-
|
|
401
|
-
const rules = new Rules({
|
|
402
|
-
AppName: 'Bat',
|
|
403
|
-
Version: 0,
|
|
404
|
-
RuleSet: { default: { SemVer: '3.2.1-beta3', AttributeName: '', AttributeValue: '' } },
|
|
405
|
-
});
|
|
406
|
-
await rules.Save(dbManager);
|
|
407
|
-
|
|
408
|
-
// Call the handler
|
|
409
|
-
const response = await GetRoute({ dbManager, rawPath: '/favicon.ico' });
|
|
410
|
-
|
|
411
|
-
expect(response).toBeDefined();
|
|
412
|
-
expect(response).toHaveProperty('statusCode');
|
|
413
|
-
expect(response.statusCode).toBe(404);
|
|
414
|
-
});
|
|
415
|
-
});
|
|
416
|
-
|
|
417
|
-
describe('StartupType: direct', () => {
|
|
418
|
-
it('should serve direct app with sub-route', async () => {
|
|
419
|
-
const AppName = 'DirectBat126';
|
|
420
|
-
const app = new Application({
|
|
421
|
-
AppName,
|
|
422
|
-
DisplayName: 'Bat App',
|
|
423
|
-
});
|
|
424
|
-
await app.Save(dbManager);
|
|
425
|
-
|
|
426
|
-
const version = new Version({
|
|
427
|
-
AppName,
|
|
428
|
-
DefaultFile: 'someFile.html',
|
|
429
|
-
IntegrationID: 'abcd',
|
|
430
|
-
SemVer: '3.2.1-beta3',
|
|
431
|
-
Status: 'deployed',
|
|
432
|
-
Type: 'lambda-url',
|
|
433
|
-
StartupType: 'direct',
|
|
434
|
-
URL: 'https://abc123.lambda-url.us-east-1.on.aws',
|
|
435
|
-
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:my-function',
|
|
436
|
-
});
|
|
437
|
-
await version.Save(dbManager);
|
|
438
|
-
|
|
439
|
-
const rules = new Rules({
|
|
440
|
-
AppName,
|
|
441
|
-
Version: 0,
|
|
442
|
-
RuleSet: { default: { SemVer: '3.2.1-beta3', AttributeName: '', AttributeValue: '' } },
|
|
443
|
-
});
|
|
444
|
-
await rules.Save(dbManager);
|
|
445
|
-
|
|
446
|
-
// Call the handler
|
|
447
|
-
const response = await GetRoute({ dbManager, rawPath: `/${AppName}/demo` });
|
|
448
|
-
|
|
449
|
-
expect(response).toBeDefined();
|
|
450
|
-
expect(response).toHaveProperty('statusCode');
|
|
451
|
-
expect(response.statusCode).toBe(200);
|
|
452
|
-
expect(response.appName).toBe(AppName);
|
|
453
|
-
expect(response.semVer).toBe('3.2.1-beta3');
|
|
454
|
-
expect(response.url).toBe('https://abc123.lambda-url.us-east-1.on.aws');
|
|
455
|
-
});
|
|
456
|
-
|
|
457
|
-
describe('/_next/data/ no-basePath', () => {
|
|
458
|
-
const testCases = [
|
|
459
|
-
{
|
|
460
|
-
AppName: 'DirectBatNextData',
|
|
461
|
-
SemVer: '3.2.1-beta3',
|
|
462
|
-
Locales: ['en'],
|
|
463
|
-
LambdaFunctionURL: 'https://abc123.lambda-url.us-east-1.on.aws',
|
|
464
|
-
RawPath: '/_next/data/3.2.1-beta3/directbatnextdata/demo.json',
|
|
465
|
-
},
|
|
466
|
-
{
|
|
467
|
-
AppName: 'AnotherAppName',
|
|
468
|
-
SemVer: '1.0.0',
|
|
469
|
-
Locales: ['en'],
|
|
470
|
-
LambdaFunctionURL: 'https://abc124.lambda-url.us-east-1.on.aws',
|
|
471
|
-
RawPath: '/_next/data/1.0.0/anotherappname.json',
|
|
472
|
-
},
|
|
473
|
-
{
|
|
474
|
-
AppName: 'AppWithLocales',
|
|
475
|
-
SemVer: '1.0.0',
|
|
476
|
-
Locales: ['en', 'sv'],
|
|
477
|
-
LambdaFunctionURL: 'https://abc125.lambda-url.us-east-1.on.aws',
|
|
478
|
-
RawPath: '/_next/data/1.0.0/sv/appwithlocales.json',
|
|
479
|
-
},
|
|
480
|
-
{
|
|
481
|
-
AppName: 'ComplicatedLocales',
|
|
482
|
-
SemVer: '1.0.0',
|
|
483
|
-
Locales: ['en', 'en-US', 'sv', 'zh-Hant'],
|
|
484
|
-
LambdaFunctionURL: 'https://abc125.lambda-url.us-east-1.on.aws',
|
|
485
|
-
RawPath: '/_next/data/1.0.0/en-US/complicatedlocales.json',
|
|
486
|
-
},
|
|
487
|
-
{
|
|
488
|
-
AppName: 'ComplicatedLocales',
|
|
489
|
-
SemVer: '1.0.0',
|
|
490
|
-
Locales: ['en', 'en-US', 'sv', 'zh-Hant'],
|
|
491
|
-
LambdaFunctionURL: 'https://abc125.lambda-url.us-east-1.on.aws',
|
|
492
|
-
RawPath: '/_next/data/1.0.0/en-US/complicatedlocales/index.json',
|
|
493
|
-
},
|
|
494
|
-
// Add more test cases as needed
|
|
495
|
-
];
|
|
496
|
-
|
|
497
|
-
it.each(testCases)(
|
|
498
|
-
'should serve direct app with $RawPath route',
|
|
499
|
-
async ({ AppName, SemVer, LambdaFunctionURL, Locales = [], RawPath }) => {
|
|
500
|
-
const app = new Application({
|
|
501
|
-
AppName,
|
|
502
|
-
DisplayName: 'Bat App',
|
|
503
|
-
});
|
|
504
|
-
await app.Save(dbManager);
|
|
505
|
-
|
|
506
|
-
const version = new Version({
|
|
507
|
-
AppName,
|
|
508
|
-
DefaultFile: 'someFile.html',
|
|
509
|
-
IntegrationID: 'abcd',
|
|
510
|
-
SemVer,
|
|
511
|
-
Status: 'deployed',
|
|
512
|
-
Type: 'lambda-url',
|
|
513
|
-
StartupType: 'direct',
|
|
514
|
-
URL: LambdaFunctionURL,
|
|
515
|
-
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:my-function',
|
|
516
|
-
});
|
|
517
|
-
await version.Save(dbManager);
|
|
518
|
-
|
|
519
|
-
const rules = new Rules({
|
|
520
|
-
AppName,
|
|
521
|
-
Version: 0,
|
|
522
|
-
RuleSet: { default: { SemVer, AttributeName: '', AttributeValue: '' } },
|
|
523
|
-
});
|
|
524
|
-
await rules.Save(dbManager);
|
|
525
|
-
|
|
526
|
-
// Call the handler
|
|
527
|
-
const response = await GetRoute({
|
|
528
|
-
dbManager,
|
|
529
|
-
locales: Locales,
|
|
530
|
-
rawPath: RawPath,
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
expect(response).toBeDefined();
|
|
534
|
-
expect(response).toHaveProperty('statusCode');
|
|
535
|
-
expect(response.appName).toBe(AppName.toLowerCase());
|
|
536
|
-
expect(response.semVer).toBe(SemVer);
|
|
537
|
-
expect(response.statusCode).toBe(200);
|
|
538
|
-
expect(response.url).toBe(LambdaFunctionURL);
|
|
539
|
-
},
|
|
540
|
-
);
|
|
541
|
-
});
|
|
542
|
-
|
|
543
|
-
it('should serve direct app with /_next/data/[semver]/[appname]/route route', async () => {
|
|
544
|
-
const AppName = 'DirectBatNextData';
|
|
545
|
-
const app = new Application({
|
|
546
|
-
AppName,
|
|
547
|
-
DisplayName: 'Bat App',
|
|
548
|
-
});
|
|
549
|
-
await app.Save(dbManager);
|
|
550
|
-
|
|
551
|
-
const version = new Version({
|
|
552
|
-
AppName,
|
|
553
|
-
DefaultFile: 'someFile.html',
|
|
554
|
-
IntegrationID: 'abcd',
|
|
555
|
-
SemVer: '3.2.1-beta3',
|
|
556
|
-
Status: 'deployed',
|
|
557
|
-
Type: 'lambda-url',
|
|
558
|
-
StartupType: 'direct',
|
|
559
|
-
URL: 'https://abc123.lambda-url.us-east-1.on.aws',
|
|
560
|
-
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:my-function',
|
|
561
|
-
});
|
|
562
|
-
await version.Save(dbManager);
|
|
563
|
-
|
|
564
|
-
const rules = new Rules({
|
|
565
|
-
AppName,
|
|
566
|
-
Version: 0,
|
|
567
|
-
RuleSet: { default: { SemVer: '3.2.1-beta3', AttributeName: '', AttributeValue: '' } },
|
|
568
|
-
});
|
|
569
|
-
await rules.Save(dbManager);
|
|
570
|
-
|
|
571
|
-
// Call the handler
|
|
572
|
-
const response = await GetRoute({
|
|
573
|
-
dbManager,
|
|
574
|
-
rawPath: `/_next/data/3.2.1-beta3/${AppName}/demo`,
|
|
575
|
-
});
|
|
576
|
-
|
|
577
|
-
expect(response).toBeDefined();
|
|
578
|
-
expect(response).toHaveProperty('statusCode');
|
|
579
|
-
expect(response.appName).toBe(AppName);
|
|
580
|
-
expect(response.semVer).toBe('3.2.1-beta3');
|
|
581
|
-
expect(response.statusCode).toBe(200);
|
|
582
|
-
expect(response.url).toBe('https://abc123.lambda-url.us-east-1.on.aws');
|
|
583
|
-
});
|
|
584
|
-
});
|
|
585
|
-
});
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import mockFs from 'mock-fs';
|
|
2
|
-
import { loadAppFrame } from './load-app-frame';
|
|
3
|
-
import Log from './lib/log';
|
|
4
|
-
|
|
5
|
-
describe('loadAppFrame', () => {
|
|
6
|
-
afterEach(() => {
|
|
7
|
-
mockFs.restore();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('should load appFrame.html from the default basePath', () => {
|
|
11
|
-
const mockHtmlContent = '<html><body>App Frame</body></html>';
|
|
12
|
-
mockFs({
|
|
13
|
-
'appFrame.html': mockHtmlContent,
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
expect(loadAppFrame({})).toBe(mockHtmlContent);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should load appFrame.html from a custom basePath', () => {
|
|
20
|
-
const mockHtmlContent = '<html><body>App Frame</body></html>';
|
|
21
|
-
const customBasePath = './custom';
|
|
22
|
-
mockFs({
|
|
23
|
-
[customBasePath]: {
|
|
24
|
-
'appFrame.html': mockHtmlContent,
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
expect(loadAppFrame({ basePath: customBasePath })).toBe(mockHtmlContent);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('should throw an error if appFrame.html is not found', () => {
|
|
32
|
-
mockFs({});
|
|
33
|
-
|
|
34
|
-
expect(() => {
|
|
35
|
-
loadAppFrame({});
|
|
36
|
-
}).toThrowError('appFrame.html not found');
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should log the error if appFrame.html is not found', () => {
|
|
40
|
-
mockFs({});
|
|
41
|
-
const logSpy = jest.spyOn(Log.Instance, 'error');
|
|
42
|
-
|
|
43
|
-
try {
|
|
44
|
-
loadAppFrame({});
|
|
45
|
-
} catch {
|
|
46
|
-
// Catch the error to allow the test to continue
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
expect(logSpy).toHaveBeenCalledWith('appFrame.html not found');
|
|
50
|
-
});
|
|
51
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { normalizePathPrefix } from './normalize-path-prefix';
|
|
2
|
-
|
|
3
|
-
describe('normalizePathPrefix', () => {
|
|
4
|
-
it('should return an empty string when the input is an empty string', () => {
|
|
5
|
-
expect(normalizePathPrefix('')).toBe('');
|
|
6
|
-
});
|
|
7
|
-
|
|
8
|
-
it('should add a leading slash if it does not exist', () => {
|
|
9
|
-
expect(normalizePathPrefix('path')).toBe('/path');
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it('should not add a leading slash if it already exists', () => {
|
|
13
|
-
expect(normalizePathPrefix('/path')).toBe('/path');
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it('should remove a trailing slash if it exists', () => {
|
|
17
|
-
expect(normalizePathPrefix('/path/')).toBe('/path');
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should remove a trailing slash and add a leading slash if needed', () => {
|
|
21
|
-
expect(normalizePathPrefix('path/')).toBe('/path');
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should return the same input when it starts with a slash and does not end with a slash', () => {
|
|
25
|
-
expect(normalizePathPrefix('/path/subpath')).toBe('/path/subpath');
|
|
26
|
-
});
|
|
27
|
-
});
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { DBManager, Version } from '@pwrdrvr/microapps-datalib';
|
|
2
|
-
import { AppVersionCache } from './app-cache';
|
|
3
|
-
import { RedirectToDefaultFile } from './redirect-default-file';
|
|
4
|
-
|
|
5
|
-
jest.mock('./app-cache');
|
|
6
|
-
|
|
7
|
-
describe('RedirectToDefaultFile', () => {
|
|
8
|
-
const mockDbManager = {} as DBManager;
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
jest.clearAllMocks();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
it('should return undefined if GetVersionInfo throws an error', async () => {
|
|
15
|
-
(AppVersionCache.GetInstance as jest.Mock).mockImplementation(() => {
|
|
16
|
-
return {
|
|
17
|
-
GetVersionInfo: () => {
|
|
18
|
-
throw new Error('GetVersionInfo error');
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
const result = await RedirectToDefaultFile({
|
|
24
|
-
dbManager: mockDbManager,
|
|
25
|
-
appName: 'testApp',
|
|
26
|
-
semVer: '1.0.0',
|
|
27
|
-
appNameOrRootTrailingSlash: '',
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
expect(result).toBeUndefined();
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
it('should return undefined if versionInfo is undefined', async () => {
|
|
34
|
-
(AppVersionCache.GetInstance as jest.Mock).mockImplementation(() => {
|
|
35
|
-
return {
|
|
36
|
-
GetVersionInfo: () => undefined,
|
|
37
|
-
};
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
const result = await RedirectToDefaultFile({
|
|
41
|
-
dbManager: mockDbManager,
|
|
42
|
-
appName: 'testApp',
|
|
43
|
-
semVer: '1.0.0',
|
|
44
|
-
appNameOrRootTrailingSlash: '',
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
expect(result).toBeUndefined();
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
it('should return undefined if versionInfo.DefaultFile is not set', async () => {
|
|
51
|
-
const versionInfo: Version = {
|
|
52
|
-
AppName: 'testApp',
|
|
53
|
-
SemVer: '1.0.0',
|
|
54
|
-
// @ts-expect-error this is a test after-all
|
|
55
|
-
DefaultFile: undefined,
|
|
56
|
-
};
|
|
57
|
-
(AppVersionCache.GetInstance as jest.Mock).mockImplementation(() => {
|
|
58
|
-
return {
|
|
59
|
-
GetVersionInfo: () => versionInfo,
|
|
60
|
-
};
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
const result = await RedirectToDefaultFile({
|
|
64
|
-
dbManager: mockDbManager,
|
|
65
|
-
appName: 'testApp',
|
|
66
|
-
semVer: '1.0.0',
|
|
67
|
-
appNameOrRootTrailingSlash: '',
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
expect(result).toBeUndefined();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
it('should return a redirect with status code 302 when versionInfo.DefaultFile is set', async () => {
|
|
74
|
-
// @ts-expect-error This is ok to be incomplete for the test
|
|
75
|
-
const versionInfo: Version = {
|
|
76
|
-
AppName: 'testApp',
|
|
77
|
-
SemVer: '1.0.0',
|
|
78
|
-
DefaultFile: 'index.html',
|
|
79
|
-
};
|
|
80
|
-
(AppVersionCache.GetInstance as jest.Mock).mockImplementation(() => {
|
|
81
|
-
return {
|
|
82
|
-
GetVersionInfo: () => versionInfo,
|
|
83
|
-
};
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
const result = await RedirectToDefaultFile({
|
|
87
|
-
dbManager: mockDbManager,
|
|
88
|
-
appName: 'testApp',
|
|
89
|
-
semVer: '1.0.0',
|
|
90
|
-
appNameOrRootTrailingSlash: 'testapp/',
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
expect(result).toEqual({
|
|
94
|
-
statusCode: 302,
|
|
95
|
-
redirectLocation: '/testapp/1.0.0/index.html',
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
});
|
package/src/route-app.spec.ts
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { DBManager } from '@pwrdrvr/microapps-datalib';
|
|
2
|
-
import { AppVersionCache } from './app-cache';
|
|
3
|
-
import { RouteApp } from './route-app';
|
|
4
|
-
|
|
5
|
-
jest.mock('./app-cache');
|
|
6
|
-
|
|
7
|
-
describe('RouteApp', () => {
|
|
8
|
-
const mockDbManager = {} as DBManager;
|
|
9
|
-
|
|
10
|
-
afterEach(() => {
|
|
11
|
-
jest.clearAllMocks();
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
const testCases = [
|
|
15
|
-
{
|
|
16
|
-
caseName: 'should route simple app with iframe startup and no versions specified',
|
|
17
|
-
possibleSemVerPathAfterAppVersionInfo: undefined,
|
|
18
|
-
possibleSemVerPathNextDataVersionInfo: undefined,
|
|
19
|
-
possibleSemVerQueryVersionInfo: undefined,
|
|
20
|
-
possibleSemVerQuery: undefined,
|
|
21
|
-
defaultVersion: '1.0.0',
|
|
22
|
-
expectedStatusCode: 200,
|
|
23
|
-
expectedAppName: 'testApp',
|
|
24
|
-
expectedSemVer: '1.0.0',
|
|
25
|
-
expectedStartupType: 'iframe',
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
caseName: 'uses the path specified version instead of the default version',
|
|
29
|
-
possibleSemVerPathAfterAppVersionInfo: {
|
|
30
|
-
SemVer: '1.0.1',
|
|
31
|
-
DefaultFile: 'index.html',
|
|
32
|
-
StartupType: 'iframe',
|
|
33
|
-
},
|
|
34
|
-
possibleSemVerPathNextDataVersionInfo: undefined,
|
|
35
|
-
possibleSemVerQueryVersionInfo: undefined,
|
|
36
|
-
possibleSemVerQuery: undefined,
|
|
37
|
-
defaultVersion: '1.0.0',
|
|
38
|
-
expectedStatusCode: 200,
|
|
39
|
-
expectedAppName: 'testApp',
|
|
40
|
-
expectedSemVer: '1.0.1',
|
|
41
|
-
expectedStartupType: undefined,
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
caseName: 'uses the query string specified version instead of the default version',
|
|
45
|
-
possibleSemVerPathAfterAppVersionInfo: undefined,
|
|
46
|
-
possibleSemVerPathNextDataVersionInfo: undefined,
|
|
47
|
-
possibleSemVerQueryVersionInfo: {
|
|
48
|
-
SemVer: '1.0.3',
|
|
49
|
-
DefaultFile: 'index.html',
|
|
50
|
-
StartupType: 'iframe',
|
|
51
|
-
},
|
|
52
|
-
possibleSemVerQuery: '1.0.3',
|
|
53
|
-
defaultVersion: '1.0.0',
|
|
54
|
-
expectedStatusCode: 200,
|
|
55
|
-
expectedAppName: 'testApp',
|
|
56
|
-
expectedSemVer: '1.0.3',
|
|
57
|
-
expectedStartupType: 'iframe',
|
|
58
|
-
},
|
|
59
|
-
{
|
|
60
|
-
caseName: 'gives a 404 when the query string version does not exist',
|
|
61
|
-
possibleSemVerPathAfterAppVersionInfo: undefined,
|
|
62
|
-
possibleSemVerPathNextDataVersionInfo: undefined,
|
|
63
|
-
possibleSemVerQueryVersionInfo: undefined,
|
|
64
|
-
possibleSemVerQuery: '1.0.4',
|
|
65
|
-
defaultVersion: '1.0.0',
|
|
66
|
-
expectedStatusCode: 404,
|
|
67
|
-
expectedAppName: undefined,
|
|
68
|
-
expectedSemVer: undefined,
|
|
69
|
-
expectedStartupType: undefined,
|
|
70
|
-
},
|
|
71
|
-
];
|
|
72
|
-
|
|
73
|
-
it.each(testCases)(
|
|
74
|
-
'$caseName',
|
|
75
|
-
async ({
|
|
76
|
-
possibleSemVerPathAfterAppVersionInfo,
|
|
77
|
-
possibleSemVerPathNextDataVersionInfo,
|
|
78
|
-
possibleSemVerQueryVersionInfo,
|
|
79
|
-
possibleSemVerQuery,
|
|
80
|
-
defaultVersion,
|
|
81
|
-
expectedStatusCode,
|
|
82
|
-
expectedAppName,
|
|
83
|
-
expectedSemVer,
|
|
84
|
-
expectedStartupType,
|
|
85
|
-
}) => {
|
|
86
|
-
(AppVersionCache.GetInstance as jest.Mock).mockImplementation(() => {
|
|
87
|
-
return {
|
|
88
|
-
GetVersionInfo: (options: { key: { AppName: string; SemVer: string } }) => {
|
|
89
|
-
if (options.key.SemVer === 'pathAfterApp') {
|
|
90
|
-
return possibleSemVerPathAfterAppVersionInfo;
|
|
91
|
-
}
|
|
92
|
-
if (options.key.SemVer === 'pathNextData') {
|
|
93
|
-
return possibleSemVerPathNextDataVersionInfo;
|
|
94
|
-
}
|
|
95
|
-
if (options.key.SemVer === 'query') {
|
|
96
|
-
return possibleSemVerQueryVersionInfo;
|
|
97
|
-
}
|
|
98
|
-
if (options.key.SemVer === defaultVersion) {
|
|
99
|
-
return { ...options.key, DefaultFile: 'index.html', StartupType: 'iframe' };
|
|
100
|
-
}
|
|
101
|
-
return undefined;
|
|
102
|
-
},
|
|
103
|
-
GetRules: () => ({ RuleSet: { default: { SemVer: defaultVersion } } }),
|
|
104
|
-
};
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
const result = await RouteApp({
|
|
108
|
-
dbManager: mockDbManager,
|
|
109
|
-
event: { dbManager: mockDbManager, locales: [], rawPath: '/testApp' },
|
|
110
|
-
appName: 'testApp',
|
|
111
|
-
possibleSemVerPathNextData: possibleSemVerPathNextDataVersionInfo
|
|
112
|
-
? 'pathNextData'
|
|
113
|
-
: undefined,
|
|
114
|
-
possibleSemVerPathAfterApp: possibleSemVerPathAfterAppVersionInfo
|
|
115
|
-
? 'pathAfterApp'
|
|
116
|
-
: undefined,
|
|
117
|
-
possibleSemVerQuery: possibleSemVerQueryVersionInfo ? 'query' : possibleSemVerQuery,
|
|
118
|
-
additionalParts: '',
|
|
119
|
-
appNameOrRootTrailingSlash: '',
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
expect(result.statusCode).toBe(expectedStatusCode);
|
|
123
|
-
expect(result.appName).toBe(expectedAppName);
|
|
124
|
-
expect(result.semVer).toBe(expectedSemVer);
|
|
125
|
-
expect(result.startupType).toBe(expectedStartupType);
|
|
126
|
-
},
|
|
127
|
-
);
|
|
128
|
-
});
|