Skip to content

Commit 9fcaf6d

Browse files
authored
fix: wrong version negotiation for OpenUI5 framework (#561)
* fix: wrong version negotiation for OpenUI5 fr-work * fix: work on pr comment
1 parent 9b872b1 commit 9fcaf6d

File tree

12 files changed

+262
-82
lines changed

12 files changed

+262
-82
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
"lint-staged": "10.5.3",
6565
"make-dir": "3.1.0",
6666
"mocha": "10.0.0",
67+
"mock-fs": "^5.2.0",
6768
"npm-run-all": "4.1.5",
6869
"nyc": "15.1.0",
6970
"prettier": "2.2.1",

packages/context/src/ui5-model.ts

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -292,11 +292,14 @@ async function getLibs(
292292
}
293293

294294
// if library is not found, resolve next minor highest patch
295-
let versionMap: Record<
296-
string,
297-
{ version: string; support: string; lts: boolean }
298-
>; // just an in-memory cache!
299-
const resolvedVersions: Record<string, string> = Object.create(null);
295+
const versionMap: Record<
296+
UI5Framework,
297+
Record<string, { version: string; support: string; lts: boolean }>
298+
> = Object.create(null); // just an in-memory cache!
299+
const resolvedVersions: Record<
300+
UI5Framework,
301+
Record<string, string>
302+
> = Object.create(null);
300303
/*
301304
* VERSION RESOLUTION LOGIC:
302305
* =========================
@@ -353,17 +356,18 @@ export async function negotiateVersionWithFetcher(
353356
// try to negotiate version
354357
let isFallback = false;
355358
let isIncorrectVersion = false;
359+
let versions = versionMap[framework];
356360
if (!version) {
357361
// no version defined, using default version
358362
getLogger().warn(
359363
"No version defined! Please check the minUI5Version in your manifest.json!"
360364
);
361365
version = DEFAULT_UI5_VERSION;
362366
isFallback = true;
363-
} else if (resolvedVersions[version]) {
367+
} else if (resolvedVersions[framework]?.[version]) {
364368
// version already resolved?
365369
const versionDefined = version;
366-
version = resolvedVersions[version];
370+
version = resolvedVersions[framework]?.[version];
367371
if (versionDefined !== version) {
368372
isIncorrectVersion = true;
369373
}
@@ -377,12 +381,12 @@ export async function negotiateVersionWithFetcher(
377381
) {
378382
const requestedVersion = version;
379383
// no version information found, try to negotiate the version
380-
if (!versionMap) {
384+
if (!versions) {
381385
// retrieve the version mapping (only exists for SAPUI5 so far)
382-
const url = getVersionJsonUrl();
386+
const url = getVersionJsonUrl(framework);
383387
const response = await versionJsonFetcher(url);
384388
if (response.ok) {
385-
versionMap = (await response.json()) as Record<
389+
versionMap[framework] = (await response.json()) as Record<
386390
string,
387391
{ version: string; support: string; lts: boolean }
388392
>;
@@ -395,22 +399,23 @@ export async function negotiateVersionWithFetcher(
395399
DEFAULT_UI5_VERSION,
396400
}
397401
);
398-
versionMap = {
402+
versionMap[framework] = {
399403
latest: {
400404
version: DEFAULT_UI5_VERSION,
401405
support: "Maintenance",
402406
lts: true,
403407
},
404408
};
405409
}
410+
versions = versionMap[framework];
406411
}
407412
// coerce the version (check for invalid version, which indicates development scenario)
408413
const parsedVersion = semver.coerce(version);
409414
if (parsedVersion) {
410-
if (versionMap[`${parsedVersion.major}.${parsedVersion.minor}`]) {
415+
if (versions[`${parsedVersion.major}.${parsedVersion.minor}`]) {
411416
// lookup for a valid major.minor entry
412417
version =
413-
versionMap[`${parsedVersion.major}.${parsedVersion.minor}`].version;
418+
versions[`${parsedVersion.major}.${parsedVersion.minor}`].version;
414419
}
415420
if (
416421
!(await getVersionInfo(
@@ -423,25 +428,28 @@ export async function negotiateVersionWithFetcher(
423428
// find closest supported version
424429
version =
425430
semverMinSatisfying(
426-
Object.values(versionMap).map((entry) => {
431+
Object.values(versions).map((entry) => {
427432
return entry.version;
428433
}) as string[],
429434
`^${version}`
430-
) || versionMap["latest"].version;
435+
) || versions["latest"].version;
431436

432437
isIncorrectVersion = true;
433438
}
434439
} else {
435440
// development scenario => use latest version
436-
version = versionMap["latest"].version;
441+
version = versions["latest"].version;
437442
isIncorrectVersion = true;
438443
}
439444
// store the resolved version
440445
if (requestedVersion) {
441446
if (requestedVersion !== version) {
442447
isIncorrectVersion = true;
443448
}
444-
resolvedVersions[requestedVersion] = version;
449+
if (!resolvedVersions[framework]) {
450+
resolvedVersions[framework] = Object.create(null);
451+
}
452+
resolvedVersions[framework][requestedVersion] = version;
445453
}
446454
}
447455
return {

packages/context/src/ui5-yaml.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,18 +99,19 @@ async function readUI5YamlFile(
9999
export async function findYamlPath(
100100
documentPath: string
101101
): Promise<string | undefined> {
102-
return findUp(FileName.Ui5Yaml, { cwd: documentPath });
102+
return await findUp(FileName.Ui5Yaml, { cwd: documentPath });
103103
}
104104

105105
/**
106106
* Get yaml of an app
107107
* @param ui5YamlRoot absolute root to a yaml file of an app e.g. /some/other/path/parts/app/manage_travels/webapp/ui5.yaml
108108
*/
109109
export async function getUI5Yaml(
110-
ui5YamlRoot: string
110+
ui5YamlRoot: string,
111+
ignoreCache?: boolean
111112
): Promise<YamlDetails | undefined> {
112113
const cachedYaml = cache.getYamlDetails(ui5YamlRoot);
113-
if (cachedYaml) {
114+
if (cachedYaml && !ignoreCache) {
114115
return cachedYaml;
115116
}
116117
try {
@@ -130,13 +131,14 @@ export async function getUI5Yaml(
130131
* @param documentPath path to a file e.g. absolute/path/webapp/ext/main/Main.view.xml
131132
*/
132133
export async function getYamlDetails(
133-
documentPath: string
134+
documentPath: string,
135+
ignoreCache?: boolean
134136
): Promise<YamlDetails> {
135137
const yamlPath = await findYamlPath(documentPath);
136138
if (!yamlPath) {
137139
return { framework: DEFAULT_UI5_FRAMEWORK, version: undefined };
138140
}
139-
const yamlData = await getUI5Yaml(yamlPath);
141+
const yamlData = await getUI5Yaml(yamlPath, ignoreCache);
140142
if (yamlData) {
141143
return yamlData;
142144
}

packages/context/src/utils/ui5.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,8 @@ export function getCDNBaseUrl(
1212
return url;
1313
}
1414

15-
export function getVersionJsonUrl(/* framework: UI5Framework */): string {
16-
// version.json is only supported for SAPUI5 right now
17-
return `${UI5_FRAMEWORK_CDN_BASE_URL["SAPUI5"]}version.json`;
15+
export function getVersionJsonUrl(framework: UI5Framework): string {
16+
return `${UI5_FRAMEWORK_CDN_BASE_URL[framework]}version.json`;
1817
}
1918

2019
export function getVersionInfoUrl(

packages/context/src/watcher.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export const reactOnUI5YamlChange = async (
9494
case 1: //created
9595
case 2: {
9696
//changed
97-
const response = await getYamlDetails(ui5YamlUri);
97+
const response = await getYamlDetails(ui5YamlPath, true);
9898
// We want to keep last successfully read state - yaml file may be actively edited
9999
cache.setYamlDetails(ui5YamlPath, response);
100100
return;

packages/context/test/loader-spec.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { Manifest } from "@sap-ux/project-access";
1616
import { ProjectKind, UI5_PROJECT_TYPE } from "../src/types";
1717
import { getProjectData } from "./utils";
1818
import { getManifestDetails, getUI5Manifest } from "../src/manifest";
19+
import { getApp } from "../src/loader";
1920

2021
describe("loader", () => {
2122
let testFramework: TestFramework;
@@ -121,7 +122,7 @@ describe("loader", () => {
121122
expect(getAppSpy).to.have.been.called;
122123
expect(app).to.deep.equal(getAppSpy.returnValues[0]);
123124
});
124-
it("does not fined mainService and returns undefined", async () => {
125+
it("does not find mainService and returns empty services", async () => {
125126
const projectRoot = testFramework.getProjectRoot();
126127
const { appRoot, manifestDetails, projectInfo } = await getProjectData(
127128
projectRoot
@@ -136,9 +137,9 @@ describe("loader", () => {
136137
manifestDetails,
137138
projectInfo
138139
);
139-
expect(app).to.be.undefined;
140+
expect(app?.localServices.size).to.eq(0);
140141
});
141-
it("does not parser service files and returns undefined", async () => {
142+
it("does not parse service files and returns empty services", async () => {
142143
const parseServiceFilesStub = stub(parser, "parseServiceFiles").returns(
143144
undefined
144145
);
@@ -151,15 +152,15 @@ describe("loader", () => {
151152
} = await getProjectData(projectRoot);
152153
// for consistency remove cache
153154
cache.deleteApp(appRoot);
154-
const app = await loader.getApp(
155+
const app = await getApp(
155156
projectRoot,
156157
appRoot,
157158
manifest,
158159
manifestDetails,
159160
projectInfo
160161
);
161162
expect(parseServiceFilesStub).to.have.been.called;
162-
expect(app).to.be.undefined;
163+
expect(app?.localServices.size).to.eq(0);
163164
});
164165
});
165166
context("getCAPProject", () => {

packages/context/test/manifest-spec.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,16 @@ describe("manifest", () => {
3939
restore();
4040
});
4141
context("getUI5Manifest", () => {
42-
it("get undefined", async () => {
42+
it("get undefined", async function () {
43+
this.timeout(20000);
4344
const manifestRoot = join("/wrong/path", FileName.Manifest);
4445
// for consistency remove cache
4546
cache.deleteManifest(manifestRoot);
4647
const result = await getUI5Manifest(manifestRoot);
4748
expect(result).to.be.undefined;
4849
});
49-
it("get UI5 manifest", async () => {
50+
it("get UI5 manifest", async function () {
51+
this.timeout(20000);
5052
const projectRoot = testFramework.getProjectRoot();
5153
const appRoot = getAppRoot(projectRoot);
5254
const manifestRoot = join(appRoot, FileName.Manifest);

packages/context/test/services-spec.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ describe("services", () => {
2727
};
2828
testFramework = new TestFramework(useConfig);
2929
});
30+
beforeEach(() => {
31+
cache.reset();
32+
});
3033
afterEach(() => {
3134
restore();
3235
});

0 commit comments

Comments
 (0)