Skip to content

Commit

Permalink
fix(action): correctly apply bitmask for supported features
Browse files Browse the repository at this point in the history
  • Loading branch information
zachowj committed Aug 27, 2024
1 parent 526504a commit e4d4e97
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 15 deletions.
15 changes: 5 additions & 10 deletions src/editor/components/idSelector/IdSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import * as haServer from '../../haserver';
import { i18n } from '../../i18n';
import { createRow } from './elements';
import { isFeatureSupported, pushIfNotExist } from './utils';
import { createSelectOptions } from './virtual-select';

interface EditableListButton {
Expand Down Expand Up @@ -116,9 +117,10 @@ export default class IdSelector {
if (
supportedFeatures !== undefined &&
state.attributes.supported_features !== undefined &&
(state.attributes.supported_features &
supportedFeatures) ===
0
!isFeatureSupported(
state.attributes.supported_features,
supportedFeatures,
)
) {
continue;
}
Expand Down Expand Up @@ -332,10 +334,3 @@ export function getSelectedIds(elementId: string): SelectedIds {
[IdSelectorType.Regex]: Array.from(selectedIds[IdSelectorType.Regex]),
};
}

// Push an element to an array if it does not exist
function pushIfNotExist<T>(array: T[], element: T) {
if (!array.includes(element)) {
array.push(element);
}
}
29 changes: 29 additions & 0 deletions src/editor/components/idSelector/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Push an element to an array if it does not exist
export function pushIfNotExist<T>(array: T[], element: T) {
if (!array.includes(element)) {
array.push(element);
}
}

function compareBitmask(
supported: number,
required: (number | number[])[],
): boolean {
return required.some((req) => {
if (Array.isArray(req)) {
return req.every((r) => (supported & r) !== 0);
} else {
return (supported & req) !== 0;
}
});
}

export function isFeatureSupported(
bitmask: number,
required: (number | number[])[],
): boolean {
if (required.length === 0) {
return true;
}
return compareBitmask(bitmask, required);
}
8 changes: 3 additions & 5 deletions src/nodes/action/editor/targets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ type ServiceEntityFilter = {
integration?: string;
domain?: string | string[];
device_class?: string | string[];
supported_features?: number | [number];
supported_features?: (number | number[])[];
};

type ServiceFilter = {
Expand All @@ -17,7 +17,7 @@ export type ActionTargetFilter = {
integration?: string;
domain?: string[];
device_class?: string[];
supported_features?: number;
supported_features?: (number | number[])[];
};

export enum ValidTarget {
Expand All @@ -40,9 +40,7 @@ export function convertServiceEntityFilter(
: filter.device_class
? [filter.device_class]
: undefined,
supported_features: Array.isArray(filter.supported_features)
? filter.supported_features[0]
: filter.supported_features,
supported_features: filter.supported_features,
};
}

Expand Down
45 changes: 45 additions & 0 deletions test/editor/components/idSelector/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect } from 'chai';

import {
isFeatureSupported,
pushIfNotExist,
} from '../../../../src/editor/components/idSelector/utils';

describe('utils', function () {
describe('pushIfNotExist', function () {
it('should push element to array if it does not exist', function () {
const array = [1, 2, 3];
pushIfNotExist(array, 4);
expect(array).to.include(4);
});

it('should not push element to array if it already exists', function () {
const array = [1, 2, 3];
pushIfNotExist(array, 3);
expect(array).to.have.lengthOf(3);
});
});

describe('isFeatureSupported', function () {
it('should return true if required array is empty', function () {
expect(isFeatureSupported(0b1010, [])).to.be.true;
});

it('should return true if bitmask supports all required features', function () {
expect(isFeatureSupported(0b1010, [0b0010, 0b1000])).to.be.true;
});

it('should return false if bitmask does not support any required features', function () {
expect(isFeatureSupported(0b1010, [0b0100, 0b0001])).to.be.false;
});

it('should return true if bitmask supports any features ', function () {
expect(isFeatureSupported(0b1111, [[0b1000, 0b0100], 0b1000])).to.be
.true;
});

it('should return false if bitmask does not support all features in nested arrays', function () {
expect(isFeatureSupported(0b1010, [[0b1000, 0b0100]])).to.be.false;
});
});
});

0 comments on commit e4d4e97

Please sign in to comment.