Skip to content

[AI-FSSDK] [FSSDK-12368] Local Holdouts - Cleanup flag base setup and add includedRules and rule-level lookup #1548

[AI-FSSDK] [FSSDK-12368] Local Holdouts - Cleanup flag base setup and add includedRules and rule-level lookup

[AI-FSSDK] [FSSDK-12368] Local Holdouts - Cleanup flag base setup and add includedRules and rule-level lookup #1548

Triggered via pull request April 14, 2026 20:48
Status Failure
Total duration 8m 48s
Artifacts

javascript.yml

on: pull_request
Matrix: unit_tests
lint_markdown_files  /  lint
1m 13s
lint_markdown_files / lint
lint
1m 0s
lint
typescript_test
1m 28s
typescript_test
integration_tests  /  test
8s
integration_tests / test
fullstack_production_suite  /  test
5s
fullstack_production_suite / test
Matrix: browser_tests
Coveralls coverage
0s
Coveralls coverage
Fit to window
Zoom out
Zoom in

Annotations

47 errors and 23 warnings
unit_tests (24)
Process completed with exit code 2.
unit_tests (22)
The strategy configuration was canceled because "unit_tests._24" failed
unit_tests (22)
The operation was canceled.
unit_tests (20)
The strategy configuration was canceled because "unit_tests._24" failed
unit_tests (20)
The operation was canceled.
unit_tests (18)
The strategy configuration was canceled because "unit_tests._24" failed
unit_tests (18)
The operation was canceled.
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L2050
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ lib/core/decision_service/index.spec.ts:2050:41 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:28
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L456
TypeError: projectConfig.getHoldoutsForRule is not a function. (In 'projectConfig.getHoldoutsForRule(configObj, "non_existent_rule")', 'projectConfig.getHoldoutsForRule' is undefined) ❯ lib/project_config/project_config.spec.ts:456:58
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L445
TypeError: projectConfig.getHoldoutsForRule is not a function. (In 'projectConfig.getHoldoutsForRule(configObj, "3324490633")', 'projectConfig.getHoldoutsForRule' is undefined) ❯ lib/project_config/project_config.spec.ts:445:58
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L432
TypeError: projectConfig.getGlobalHoldouts is not a function. (In 'projectConfig.getGlobalHoldouts(configObj)', 'projectConfig.getGlobalHoldouts' is undefined) ❯ lib/project_config/project_config.spec.ts:432:59
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L537
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776199835161, + "uuid": "033779eb-ba22-4779-8bef-e8bbe0a6f38f", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ lib/optimizely/index.spec.ts:537:59 ❯ fulfilled lib/optimizely/index.spec.ts:25:28
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L1800
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ lib/core/decision_service/index.spec.ts:1800:45 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:28
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L395
TypeError: projectConfig.getHoldoutsForRule is not a function. (In 'projectConfig.getHoldoutsForRule(configObj, "non_existent_rule")', 'projectConfig.getHoldoutsForRule' is undefined) ❯ lib/project_config/project_config.spec.ts:395:58
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L385
TypeError: projectConfig.getHoldoutsForRule is not a function. (In 'projectConfig.getHoldoutsForRule(configObj, "3324490633")', 'projectConfig.getHoldoutsForRule' is undefined) ❯ lib/project_config/project_config.spec.ts:385:58
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L373
TypeError: projectConfig.getGlobalHoldouts is not a function. (In 'projectConfig.getGlobalHoldouts(configObj)', 'projectConfig.getGlobalHoldouts' is undefined) ❯ lib/project_config/project_config.spec.ts:373:59
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L470
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776199779208, + "uuid": "dff38296-5f72-46af-b814-6502e6ffb022", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ lib/optimizely/index.spec.ts:470:63 ❯ fulfilled lib/optimizely/index.spec.ts:25:28
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L2050
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ lib/core/decision_service/index.spec.ts:2050:33 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:24
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L456
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:456:39
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L445
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:445:39
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L432
TypeError: projectConfig.getGlobalHoldouts is not a function ❯ lib/project_config/project_config.spec.ts:432:41
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L537
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776199987723, + "uuid": "0dfdc6b2-4ab7-4e46-ae4c-353051e4ccd5", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ lib/optimizely/index.spec.ts:537:38 ❯ fulfilled lib/optimizely/index.spec.ts:25:24
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L1800
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ lib/core/decision_service/index.spec.ts:1800:38 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:24
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L395
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:395:40
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L385
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:385:40
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L373
TypeError: projectConfig.getGlobalHoldouts is not a function ❯ lib/project_config/project_config.spec.ts:373:42
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L470
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776199811386, + "uuid": "97a8a9ba-83e9-4913-a68a-7db6baf8efb8", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ lib/optimizely/index.spec.ts:470:43 ❯ fulfilled lib/optimizely/index.spec.ts:25:24
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L2050
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ lib/core/decision_service/index.spec.ts:2050:33 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:24
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L456
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:456:39
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L445
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:445:39
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L432
TypeError: projectConfig.getGlobalHoldouts is not a function ❯ lib/project_config/project_config.spec.ts:432:41
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L537
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776200012774, + "uuid": "eeff4f09-3a57-4fad-b78d-27c049b1d002", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ lib/optimizely/index.spec.ts:537:38 ❯ fulfilled lib/optimizely/index.spec.ts:25:24
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L1800
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ lib/core/decision_service/index.spec.ts:1800:38 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:24
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L395
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:395:40
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L385
TypeError: projectConfig.getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:385:40
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L373
TypeError: projectConfig.getGlobalHoldouts is not a function ❯ lib/project_config/project_config.spec.ts:373:42
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L470
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776199824842, + "uuid": "082ed250-ebea-4926-adc7-d6d4c235bd67", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ lib/optimizely/index.spec.ts:470:43 ❯ fulfilled lib/optimizely/index.spec.ts:25:24
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L2050
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ /home/runner/work/javascript-sdk/javascript-sdk/lib/core/decision_service/index.spec.ts/</</</</< lib/core/decision_service/index.spec.ts:2050:33 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:24
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L456
TypeError: (intermediate value).getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:456:39
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L445
TypeError: (intermediate value).getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:445:39
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L432
TypeError: (intermediate value).getGlobalHoldouts is not a function ❯ lib/project_config/project_config.spec.ts:432:41
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L537
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776200051404, + "uuid": "ca6cfabc-49f3-4fb0-b15c-b40dd2ecf49f", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ /home/runner/work/javascript-sdk/javascript-sdk/lib/optimizely/index.spec.ts/</</</< lib/optimizely/index.spec.ts:537:38 ❯ fulfilled lib/optimizely/index.spec.ts:25:24
lib/core/decision_service/index.spec.ts > DecisionService > resolveVariationForFeatureList - async > holdout > should consider local holdout if misses global holdout: lib/core/decision_service/index.spec.ts#L1800
AssertionError: expected { …(3) } to deeply equal { experiment: { …(9) }, …(2) } - Expected + Received { - "decisionSource": "holdout", + "decisionSource": "rollout", "experiment": { "audienceConditions": [ "or", "4002", ], "audienceIds": [ "4002", ], - "id": "holdout_included_specific_id", - "includedRules": [ - "2001", - ], - "key": "holdout_included_specific", + "forcedVariations": {}, + "id": "3002", + "isRollout": true, + "key": "delivery_2", + "layerId": "9300001480455", "status": "Running", "trafficAllocation": [ { - "endOfRange": 5000, - "entityId": "holdout_variation_included_specific_id", + "endOfRange": 4000, + "entityId": "5005", }, ], "variationKeyMap": { - "holdout_variation_included_specific": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "variation_5": { + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", }, + ], }, + }, "variations": [ { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, ], }, "variation": { - "id": "holdout_variation_included_specific_id", - "key": "holdout_variation_included_specific", - "variables": [], + "featureEnabled": true, + "id": "5005", + "key": "variation_5", + "variables": [ + { + "id": "6001", + "value": "5", + }, + ], }, } ❯ /home/runner/work/javascript-sdk/javascript-sdk/lib/core/decision_service/index.spec.ts/</</</</< lib/core/decision_service/index.spec.ts:1800:38 ❯ fulfilled lib/core/decision_service/index.spec.ts:42:24
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return empty array for non-targeted rule: lib/project_config/project_config.spec.ts#L395
TypeError: (intermediate value).getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:395:40
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return holdouts for specific rule: lib/project_config/project_config.spec.ts#L385
TypeError: (intermediate value).getHoldoutsForRule is not a function ❯ lib/project_config/project_config.spec.ts:385:40
lib/project_config/project_config.spec.ts > getGlobalHoldouts and getHoldoutsForRule > should return global holdouts: lib/project_config/project_config.spec.ts#L373
TypeError: (intermediate value).getGlobalHoldouts is not a function ❯ lib/project_config/project_config.spec.ts:373:42
lib/optimizely/index.spec.ts > Optimizely > holdout tests > should handle holdout with excluded flags: lib/optimizely/index.spec.ts#L470
AssertionError: expected "spy" to be called with arguments: [ ObjectContaining{…} ] Received: 1st spy call: @@ -1,12 +1,13 @@ [ - ObjectContaining { + { "attributes": { "age": 80, "country": "BD", }, - "experiment": { + "experiment": null, + "holdout": { "audienceConditions": [ "or", "4003", ], "audienceIds": [], @@ -54,12 +55,70 @@ "value": "3", }, ], }, ], + }, + "logEvent": { + "httpVerb": "POST", + "params": { + "account_id": "24535200037", + "anonymize_ip": true, + "client_name": "node-sdk", + "client_version": "6.3.1", + "enrich_decisions": true, + "project_id": "5088239376138240", + "revision": "21", + "visitors": [ + { + "attributes": [ + { + "entity_id": "7001", + "key": "age", + "type": "custom", + "value": 80, }, - "holdout": null, + { + "entity_id": "$opt_bot_filtering", + "key": "$opt_bot_filtering", + "type": "custom", + "value": false, + }, + ], + "snapshots": [ + { + "decisions": [ + { + "campaign_id": "9300001480451", + "experiment_id": "2003", + "metadata": { + "cmab_uuid": undefined, + "enabled": true, + "flag_key": "flag_1", + "rule_key": "exp_3", + "rule_type": "feature-test", + "variation_key": "variation_3", + }, + "variation_id": "5003", + }, + ], + "events": [ + { + "entity_id": "9300001480451", + "key": "campaign_activated", + "timestamp": 1776199830105, + "uuid": "40f0aab1-f62c-44b2-a733-9333aab9f630", + }, + ], + }, + ], + "visitor_id": "test_user", + }, + ], + }, + "url": "https://logx.optimizely.com/v1/events", + }, "userId": "test_user", "variation": { "featureEnabled": true, "id": "5003", "key": "variation_3", Number of calls: 1 ❯ /home/runner/work/javascript-sdk/javascript-sdk/lib/optimizely/index.spec.ts/</</</< lib/optimizely/index.spec.ts:470:43 ❯ fulfilled lib/optimizely/index.spec.ts:25:24
fullstack_production_suite / test
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
integration_tests / test
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
unit_tests (24)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
unit_tests (22)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
unit_tests (20)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
lint
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
lint: lib/client_factory.spec.ts#L59
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L58
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L54
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L53
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L49
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L48
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L44
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L43
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L39
Unexpected any. Specify a different type
lint: lib/client_factory.spec.ts#L38
Unexpected any. Specify a different type
unit_tests (18)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
lint_markdown_files / lint
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
typescript_test
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
browser_tests (safari)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
browser_tests (chrome)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
browser_tests (edge)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
browser_tests (firefox)
Node.js 20 actions are deprecated. The following actions are running on Node.js 20 and may not work as expected: actions/checkout@v3, actions/setup-node@v3. Actions will be forced to run with Node.js 24 by default starting June 2nd, 2026. Node.js 20 will be removed from the runner on September 16th, 2026. Please check if updated versions of these actions are available that support Node.js 24. To opt into Node.js 24 now, set the FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true environment variable on the runner or in your workflow file. Once Node.js 24 becomes the default, you can temporarily opt out by setting ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION=true. For more information see: https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/