fix: Change the not condition to exactly match the HA not condition (#2387)
BREAKING CHANGE: Changes the behavior of the `not` condition when there is more than one condition present. Users who desire the previous behavior should wrap their conditions in an `and` first. - Closes: #2383
This commit is contained in:
@@ -202,7 +202,10 @@ match.
|
|||||||
|
|
||||||
## `not`
|
## `not`
|
||||||
|
|
||||||
Evaluates to `true` if _all_ embedded conditions evaluate to `false`.
|
Evaluates to `true` if every embedded condition is `false`. At least one
|
||||||
|
condition is required.
|
||||||
|
|
||||||
|
> [!IMPORTANT] > `not` is a **NOR** operation, not a **NAND**. If _any_ sub-condition is `true`, the `not` condition evaluates to `false` — even if other sub-conditions are `false`. To pass, _all_ sub-conditions must be `false`. This behavior matches the [Home Assistant equivalent](https://www.home-assistant.io/docs/scripts/conditions/#not-condition).
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
conditions:
|
conditions:
|
||||||
@@ -213,7 +216,7 @@ conditions:
|
|||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
| ------------ | --------------------------------------------------------------------------------------------------------------- |
|
| ------------ | --------------------------------------------------------------------------------------------------------------- |
|
||||||
| `condition` | Must be `not`. |
|
| `condition` | Must be `not`. |
|
||||||
| `conditions` | A list of other conditions _all_ of which must evaluate `false` in order for this condition to evaluate `true`. |
|
| `conditions` | A list of other conditions _none_ of which must evaluate `true` in order for this condition to evaluate `true`. |
|
||||||
|
|
||||||
## `numeric_state`
|
## `numeric_state`
|
||||||
|
|
||||||
@@ -244,7 +247,7 @@ conditions:
|
|||||||
|
|
||||||
## `screen`
|
## `screen`
|
||||||
|
|
||||||
Matches based on [media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries).
|
Matches based on [media queries](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Media_queries/Using).
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
conditions:
|
conditions:
|
||||||
@@ -252,10 +255,10 @@ conditions:
|
|||||||
# [...]
|
# [...]
|
||||||
```
|
```
|
||||||
|
|
||||||
| Parameter | Description |
|
| Parameter | Description |
|
||||||
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| `condition` | Must be `screen`. |
|
| `condition` | Must be `screen`. |
|
||||||
| `media_query` | Any valid [media query](https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries) string. Media queries must start and end with parentheses. This may be used to alter card configuration based on device/media properties (e.g. viewport width, orientation). Please note that `width` and `height` refer to the entire viewport not just the card. |
|
| `media_query` | Any valid [media query](https://developer.mozilla.org/en-US/docs/Web/CSS/Guides/Media_queries/Using) string. Media queries must start and end with parentheses. This may be used to alter card configuration based on device/media properties (e.g. viewport width, orientation). Please note that `width` and `height` refer to the entire viewport not just the card. |
|
||||||
|
|
||||||
See the [screen conditions examples](../examples.md?id=screen-conditions).
|
See the [screen conditions examples](../examples.md?id=screen-conditions).
|
||||||
|
|
||||||
@@ -334,7 +337,7 @@ conditions:
|
|||||||
|
|
||||||
## `user_agent`
|
## `user_agent`
|
||||||
|
|
||||||
Matches based on the [User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent).
|
Matches based on the [User-Agent](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/User-Agent).
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
conditions:
|
conditions:
|
||||||
|
|||||||
@@ -331,13 +331,13 @@ export class ConditionsManager implements ConditionsManagerReadonlyInterface {
|
|||||||
return { result: true, triggerData };
|
return { result: true, triggerData };
|
||||||
}
|
}
|
||||||
case 'not': {
|
case 'not': {
|
||||||
// "Not" is just an inversed `and`. There is no trigger data for "not
|
// "Not" is an inverted `or` (NOR). There is no trigger data for "not
|
||||||
// triggering".
|
// triggering".
|
||||||
return {
|
return {
|
||||||
result: !this._evaluateCondition(
|
result: !this._evaluateCondition(
|
||||||
{
|
{
|
||||||
...condition,
|
...condition,
|
||||||
condition: 'and',
|
condition: 'or',
|
||||||
},
|
},
|
||||||
newState,
|
newState,
|
||||||
oldState,
|
oldState,
|
||||||
|
|||||||
@@ -1317,17 +1317,21 @@ describe('ConditionsManager', () => {
|
|||||||
stateManager,
|
stateManager,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Neither sub-condition is true initially, so `not` passes.
|
||||||
expect(manager.getEvaluation().result).toBeTruthy();
|
expect(manager.getEvaluation().result).toBeTruthy();
|
||||||
|
|
||||||
|
// fullscreen becomes true — any sub-condition being true means `not` fails.
|
||||||
stateManager.setState({ fullscreen: true });
|
stateManager.setState({ fullscreen: true });
|
||||||
expect(manager.getEvaluation().result).toBeTruthy();
|
expect(manager.getEvaluation().result).toBeFalsy();
|
||||||
|
|
||||||
stateManager.setState({ expand: true });
|
stateManager.setState({ expand: true });
|
||||||
expect(manager.getEvaluation().result).toBeFalsy();
|
expect(manager.getEvaluation().result).toBeFalsy();
|
||||||
|
|
||||||
|
// fullscreen reverts, but expand is still true, so `not` still fails.
|
||||||
stateManager.setState({ fullscreen: false });
|
stateManager.setState({ fullscreen: false });
|
||||||
expect(manager.getEvaluation().result).toBeTruthy();
|
expect(manager.getEvaluation().result).toBeFalsy();
|
||||||
|
|
||||||
|
// Both sub-conditions are false again, so `not` passes.
|
||||||
stateManager.setState({ expand: false });
|
stateManager.setState({ expand: false });
|
||||||
expect(manager.getEvaluation().result).toBeTruthy();
|
expect(manager.getEvaluation().result).toBeTruthy();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user