Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/notification-services-controller/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Add exported util `isVersionInBounds` to validate version number is in bounds ([#6793](https://github.com/MetaMask/core/pull/6793))

## [18.2.0]

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export * from './constants';
export * as Mocks from './mocks';
export * as UI from './ui';
export * from '../shared';
export { isVersionInBounds } from './utils/isVersionInBounds';
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';
import type { Entry, Asset, EntryCollection } from 'contentful';
import { gt, lt } from 'semver';

import { TRIGGER_TYPES } from '../constants/notification-schema';
import { processFeatureAnnouncement } from '../processors/process-feature-announcement';
Expand All @@ -16,6 +15,7 @@ import type {
TypeMobileLinkFields,
} from '../types/feature-announcement/type-links';
import type { INotification } from '../types/notification/notification';
import { isVersionInBounds } from '../utils/isVersionInBounds';

const DEFAULT_SPACE_ID = ':space_id';
const DEFAULT_ACCESS_TOKEN = ':access_token';
Expand Down Expand Up @@ -166,33 +166,11 @@ const fetchFeatureAnnouncementNotifications = async (
const filteredRawNotifications = rawNotifications.filter((n) => {
const minVersion = n.data?.[versionKeys[env.platform].min];
const maxVersion = n.data?.[versionKeys[env.platform].max];

// If no platform version is provided, show all notifications
if (!env.platformVersion) {
return true;
}

// min/max filtering
try {
let showNotification = true;

// Check minimum version: current version must be greater than minimum
if (minVersion) {
showNotification =
showNotification && gt(env.platformVersion, minVersion);
}

// Check maximum version: current version must be less than maximum
if (maxVersion) {
showNotification =
showNotification && lt(env.platformVersion, maxVersion);
}

return showNotification;
} catch {
// something went wrong filtering, do not show notification
return false;
}
return isVersionInBounds({
currentVersion: env.platformVersion,
minVersion,
maxVersion,
});
});

return filteredRawNotifications;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
import { isVersionInBounds } from './isVersionInBounds';

describe('isVersionInBounds', () => {
const version = '7.57.0';

const minimumVersionSchema = [
{
testName: 'returns true when current version is above minimum',
minVersion: '7.56.0',
currentVersion: version,
expected: true,
},
{
testName: 'returns false when current version equals minimum',
minVersion: '7.57.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns false when current version is below minimum',
minVersion: '7.58.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns true when no minimum version is specified',
minVersion: undefined,
currentVersion: version,
expected: true,
},
{
testName: 'returns true when no current version is provided',
minVersion: '7.56.0',
currentVersion: undefined,
expected: true,
},
{
testName: 'returns false when minimum version is malformed',
minVersion: 'invalid-version',
currentVersion: version,
expected: false,
},
];

it.each(minimumVersionSchema)(
'minimum version test - $testName',
({ minVersion, currentVersion, expected }) => {
const result = isVersionInBounds({
currentVersion,
minVersion,
});
expect(result).toBe(expected);
},
);

const maximumVersionSchema = [
{
testName: 'returns true when current version is below maximum',
maxVersion: '7.58.0',
currentVersion: version,
expected: true,
},
{
testName: 'returns false when current version equals maximum',
maxVersion: '7.57.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns false when current version is above maximum',
maxVersion: '7.56.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns true when no maximum version is specified',
maxVersion: undefined,
currentVersion: version,
expected: true,
},
{
testName: 'returns true when no current version is provided',
maxVersion: '7.58.0',
currentVersion: undefined,
expected: true,
},
{
testName: 'returns false when maximum version is malformed',
maxVersion: 'invalid-version',
currentVersion: version,
expected: false,
},
];

it.each(maximumVersionSchema)(
'maximum version test - $testName',
({ maxVersion, currentVersion, expected }) => {
const result = isVersionInBounds({
currentVersion,
maxVersion,
});
expect(result).toBe(expected);
},
);

const minMaxVersionSchema = [
{
testName:
'returns true when version is within both bounds (min < current < max)',
minVersion: '7.56.0',
maxVersion: '7.58.0',
currentVersion: version,
expected: true,
},
{
testName: 'returns true when version is above minimum and below maximum',
minVersion: '7.56.5',
maxVersion: '7.57.5',
currentVersion: version,
expected: true,
},
{
testName: 'returns false when version equals minimum bound',
minVersion: '7.57.0',
maxVersion: '7.58.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns false when version equals maximum bound',
minVersion: '7.56.0',
maxVersion: '7.57.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns false when version is below minimum bound',
minVersion: '7.58.0',
maxVersion: '7.59.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns false when version is above maximum bound',
minVersion: '7.55.0',
maxVersion: '7.56.0',
currentVersion: version,
expected: false,
},
{
testName: 'returns true when both bounds are undefined',
minVersion: undefined,
maxVersion: undefined,
currentVersion: version,
expected: true,
},
{
testName:
'returns true when only minimum is defined and version is above it',
minVersion: '7.56.0',
maxVersion: undefined,
currentVersion: version,
expected: true,
},
{
testName:
'returns true when only maximum is defined and version is below it',
minVersion: undefined,
maxVersion: '7.58.0',
currentVersion: version,
expected: true,
},
{
testName:
'returns true when no current version is provided regardless of bounds',
minVersion: '7.56.0',
maxVersion: '7.58.0',
currentVersion: undefined,
expected: true,
},
{
testName:
'returns false when minimum is malformed but maximum excludes current version',
minVersion: 'malformed',
maxVersion: '7.56.0',
currentVersion: version,
expected: false,
},
{
testName:
'returns false when maximum is malformed but minimum excludes current version',
minVersion: '7.58.0',
maxVersion: 'malformed',
currentVersion: version,
expected: false,
},
];

it.each(minMaxVersionSchema)(
'min & max version bounds test - $testName',
({ minVersion, maxVersion, currentVersion, expected }) => {
const result = isVersionInBounds({
currentVersion,
minVersion,
maxVersion,
});
expect(result).toBe(expected);
},
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { gt, lt } from 'semver';

type IsVersionInBounds = {
currentVersion?: string;
minVersion?: string;
maxVersion?: string;
};

/**
* Checks if a given version is within bounds against a min and max bound
* Uses semver strings
*
* @param params - Object param containing current/min/max versions
* @param params.currentVersion - (optional) current version of application
* @param params.minVersion - (optional) exclusive min bounds
* @param params.maxVersion - (optional) exclusive max bounds
* @returns boolean is version provided is within bounds
*/
export function isVersionInBounds({
currentVersion,
minVersion,
maxVersion,
}: IsVersionInBounds) {
if (!currentVersion) {
return true;
}

try {
let showNotification = true;

// Check minimum version: current version must be greater than minimum
if (minVersion) {
showNotification = showNotification && gt(currentVersion, minVersion);
}

// Check maximum version: current version must be less than maximum
if (maxVersion) {
showNotification = showNotification && lt(currentVersion, maxVersion);
}

return showNotification;
} catch {
// something went wrong checking bounds
return false;
}
}
Loading