diff --git a/README.md b/README.md index a659173..22decbe 100644 --- a/README.md +++ b/README.md @@ -212,6 +212,7 @@ python3 ci/validate-fixtures.py | `test-case-null-operator-flag.json` | Flag using IS_NULL operator | | `test-case-null-shard-range-isolation.json` | A flag with a null shard range is removed without poisoning valid flags | | `test-case-null-targeting-key.json` | Evaluations with an explicit null targeting key | +| `test-case-optional-targeting-key.json` | Empty-key sharding, null versus empty `id` fallback, and explicit `id` precedence | | `test-case-numeric-flag.json` | Numeric flag evaluation | | `test-case-numeric-one-of.json` | Numeric ONE_OF operator matching | | `test-case-of-7-empty-targeting-key.json` | Evaluation with empty targeting key | diff --git a/evaluation-cases/test-case-optional-targeting-key.json b/evaluation-cases/test-case-optional-targeting-key.json new file mode 100644 index 0000000..9d4c7d3 --- /dev/null +++ b/evaluation-cases/test-case-optional-targeting-key.json @@ -0,0 +1,73 @@ +[ + { + "attributes": {}, + "defaultValue": "fallback", + "flag": "optional-targeting-key-sharded", + "result": { + "reason": "SPLIT", + "value": "sharded-value" + }, + "targetingKey": "", + "variationType": "STRING" + }, + { + "attributes": {}, + "defaultValue": "fallback", + "flag": "optional-targeting-key-sharded", + "result": { + "reason": "ERROR", + "value": "fallback", + "errorCode": "TARGETING_KEY_MISSING" + }, + "targetingKey": null, + "variationType": "STRING" + }, + { + "attributes": {}, + "defaultValue": "fallback", + "flag": "optional-targeting-key-id-rule", + "result": { + "reason": "TARGETING_MATCH", + "value": "empty-id-value" + }, + "targetingKey": "", + "variationType": "STRING" + }, + { + "attributes": {}, + "defaultValue": "fallback", + "flag": "optional-targeting-key-id-rule", + "result": { + "reason": "DEFAULT", + "value": "fallback" + }, + "targetingKey": null, + "variationType": "STRING" + }, + { + "attributes": { + "id": "" + }, + "defaultValue": "fallback", + "flag": "optional-targeting-key-id-rule", + "result": { + "reason": "TARGETING_MATCH", + "value": "empty-id-value" + }, + "targetingKey": null, + "variationType": "STRING" + }, + { + "attributes": { + "id": "explicit-user" + }, + "defaultValue": "fallback", + "flag": "optional-targeting-key-id-rule", + "result": { + "reason": "DEFAULT", + "value": "fallback" + }, + "targetingKey": "", + "variationType": "STRING" + } +] diff --git a/ufc-config.json b/ufc-config.json index ece892b..26a48f3 100644 --- a/ufc-config.json +++ b/ufc-config.json @@ -5092,6 +5092,75 @@ } ] }, + "optional-targeting-key-sharded": { + "key": "optional-targeting-key-sharded", + "enabled": true, + "variationType": "STRING", + "variations": { + "assigned": { + "key": "assigned", + "value": "sharded-value" + } + }, + "allocations": [ + { + "key": "sharded-allocation", + "rules": [], + "splits": [ + { + "variationKey": "assigned", + "shards": [ + { + "salt": "optional-targeting-key", + "totalShards": 10000, + "ranges": [ + { + "start": 0, + "end": 10000 + } + ] + } + ] + } + ], + "doLog": false + } + ] + }, + "optional-targeting-key-id-rule": { + "key": "optional-targeting-key-id-rule", + "enabled": true, + "variationType": "STRING", + "variations": { + "matched": { + "key": "matched", + "value": "empty-id-value" + } + }, + "allocations": [ + { + "key": "empty-id-allocation", + "rules": [ + { + "conditions": [ + { + "attribute": "id", + "operator": "MATCHES", + "value": "^$" + } + ] + } + ], + "splits": [ + { + "variationKey": "matched", + "shards": [] + } + ], + "doLog": false + } + ] + }, "semver-invalid-comparand-non-string-test": { "key": "semver-invalid-comparand-non-string-test", "enabled": true,