[ACS-10035] Ensure ADW handles no PUT for preferences API method in ACS below 25.x v. [PoC] (#4750)

* [ACS-10035]: adds evaluator and helper functions

* [ACS-10035]: disables navbar savedSearch for non-supported versions

* [ACS-10035]: extends app extension service to allow manual rule evaluation; clean up

* [ACS-10035]: introduces pipe as an alternative option for compatibility check

* [ACS-10035]: disables save search feature if is not supported

* [ACS-10035]: adds test for new method

* [ACS-10035]: sonarQube issue

* [10035]: adds unit tests for evaluators and helper fns

* [ACS-10035]: fixes failed test

* [ACS-10035]: fixes naming

* [ACS-10035]: fixes race condition issue on direct page refresh

* [ACS-10035]: fixes import

* [ACS-10035]: sonarQube issues

* [ACS-10035]: fixes sonarQube with fake versions

* [ACS-10035]: fixes tests

* [ACS-10035]: improves pipe logic stream

* [ACS-10035]: fixes sonarQube; adjusts tests

* [ACS-10035]: adds documentation

* [ACS-10035]: exposes isFeatureSupportedInCurrentAcs from aca-content lib

* [ACS-10035]: minor fixes

* [ACS-10035]: typo fix
This commit is contained in:
rmnvch
2025-09-09 07:21:52 +02:00
committed by GitHub
parent 9395d980e2
commit 74448ac12e
13 changed files with 260 additions and 16 deletions

View File

@@ -23,10 +23,10 @@
*/
import * as app from './app.rules';
import { getFileExtension } from './app.rules';
import { createVersionRule, getFileExtension, isSavedSearchAvailable } from './app.rules';
import { TestRuleContext } from './test-rule-context';
import { NodeEntry, RepositoryInfo, StatusInfo } from '@alfresco/js-api';
import { ProfileState } from '@alfresco/adf-extensions';
import { ProfileState, RuleContext } from '@alfresco/adf-extensions';
import { AppConfigService } from '@alfresco/adf-core';
describe('app.evaluators', () => {
@@ -1198,6 +1198,71 @@ describe('app.evaluators', () => {
});
});
describe('Versions compatibility', () => {
function makeContext(versionDisplay?: string): RuleContext {
return {
repository: {
version: versionDisplay ? { display: versionDisplay } : undefined
}
} as RuleContext;
}
describe('isSavedSearchAvailable', () => {
it('should return true if ACS version is equal to minimal version', () => {
expect(isSavedSearchAvailable(makeContext('25.1.0'))).toBe(true);
});
it('should return true if ACS version is greater than minimal version', () => {
expect(isSavedSearchAvailable(makeContext('25.2.0'))).toBe(true);
expect(isSavedSearchAvailable(makeContext('26.0.0'))).toBe(true);
});
it('should return false if ACS version is less than minimal version', () => {
expect(isSavedSearchAvailable(makeContext('24.4.0'))).toBe(false);
expect(isSavedSearchAvailable(makeContext('25.0.9'))).toBe(false);
});
it('should return false if ACS version is missing', () => {
expect(isSavedSearchAvailable(makeContext())).toBe(false);
expect(isSavedSearchAvailable({ repository: {} } as any)).toBe(false);
});
});
describe('createVersionRule', () => {
it('should return true if version is equal to minimal version', () => {
const rule = createVersionRule('25.1.0');
expect(rule(makeContext('25.1.0'))).toBe(true);
});
it('should return true if version is greater than minimal version', () => {
const rule = createVersionRule('25.1.0');
expect(rule(makeContext('25.2.0'))).toBe(true);
expect(rule(makeContext('26.0.0'))).toBe(true);
expect(rule(makeContext('25.1.1'))).toBe(true);
});
it('should return false if version is less than minimal version', () => {
const rule = createVersionRule('25.1.0');
expect(rule(makeContext('25.0.9'))).toBe(false);
expect(rule(makeContext('24.9.0'))).toBe(false);
});
it('should return false if version is missing', () => {
const rule = createVersionRule('25.1.0');
expect(rule(makeContext())).toBe(false);
expect(rule({ repository: {} } as any)).toBe(false);
});
it('should handle versions with different number of segments', () => {
const rule = createVersionRule('25.1.0');
expect(rule(makeContext('25.1'))).toBe(true);
expect(rule(makeContext('25.1.1'))).toBe(true);
expect(rule(makeContext('25.1.0.1-beta'))).toBe(true);
expect(rule(makeContext('25.0.1.1-rc'))).toBe(false);
});
});
});
function createTestContext(): TestRuleContext {
const context = new TestRuleContext();
context.repository = {

View File

@@ -483,6 +483,48 @@ export function canOpenWithOffice(context: AcaRuleContext): boolean {
return context.permissions.check(file, ['update']);
}
/**
* Checks if user savedSearches are supported by current ACS version.
* JSON ref: `isSavedSearchAvailable`
*/
export const isSavedSearchAvailable = createVersionRule('25.1.0');
/**
* Partially applies minimal version of a feature against a core compatibility evaluation.
* @param minimalVersion The minimal version to check against.
*/
export function createVersionRule(minimalVersion: string): (context: RuleContext) => boolean {
return (context: RuleContext): boolean => {
const acsVersion = context.repository.version?.display?.split(' ')[0];
return isVersionCompatible(acsVersion, minimalVersion);
};
}
function isVersionCompatible(currentVersion: string, minimalVersion: string): boolean {
if (!currentVersion || !minimalVersion) {
return false;
}
const currentParts = currentVersion.split('.').map(Number);
const minimalParts = minimalVersion.split('.').map(Number);
const maxLength = Math.max(currentParts.length, minimalParts.length);
for (let i = 0; i < maxLength; i++) {
const currentSegment = currentParts[i] ?? 0;
const minimalSegment = minimalParts[i] ?? 0;
if (currentSegment > minimalSegment) {
return true;
}
if (currentSegment < minimalSegment) {
return false;
}
}
return true;
}
export function isSmartFolder(context: RuleContext): boolean {
if (!context.selection?.isEmpty) {
const node = context.selection.first;