@atlaskit/tmp-editor-statsig 1.0.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/CHANGELOG.md +14 -1
  2. package/dist/cjs/experiments-config.js +56 -0
  3. package/dist/cjs/experiments.js +123 -0
  4. package/dist/cjs/index.js +5 -0
  5. package/dist/cjs/test-runner.js +83 -0
  6. package/dist/es2019/experiments-config.js +50 -0
  7. package/dist/es2019/experiments.js +110 -0
  8. package/dist/es2019/index.js +1 -0
  9. package/dist/es2019/test-runner.js +65 -0
  10. package/dist/esm/experiments-config.js +50 -0
  11. package/dist/esm/experiments.js +115 -0
  12. package/dist/esm/index.js +1 -0
  13. package/dist/esm/test-runner.js +77 -0
  14. package/dist/types/experiments-config.d.ts +43 -0
  15. package/dist/types/experiments.d.ts +66 -0
  16. package/dist/types/index.d.ts +1 -0
  17. package/dist/types/test-runner.d.ts +41 -0
  18. package/dist/types-ts4.5/experiments-config.d.ts +43 -0
  19. package/dist/types-ts4.5/experiments.d.ts +66 -0
  20. package/dist/types-ts4.5/index.d.ts +1 -0
  21. package/dist/types-ts4.5/test-runner.d.ts +41 -0
  22. package/experiments/package.json +14 -0
  23. package/package.json +9 -9
  24. package/test-runner/package.json +14 -0
  25. package/dist/cjs/feature-gate-js-client.js +0 -21
  26. package/dist/cjs/feature-gates-react.js +0 -110
  27. package/dist/es2019/feature-gate-js-client.js +0 -14
  28. package/dist/es2019/feature-gates-react.js +0 -84
  29. package/dist/esm/feature-gate-js-client.js +0 -14
  30. package/dist/esm/feature-gates-react.js +0 -101
  31. package/dist/types/feature-gate-js-client.d.ts +0 -12
  32. package/dist/types/feature-gates-react.d.ts +0 -19
  33. package/dist/types-ts4.5/feature-gate-js-client.d.ts +0 -12
  34. package/dist/types-ts4.5/feature-gates-react.d.ts +0 -19
  35. package/feature-gate-js-client/package.json +0 -14
  36. package/feature-gates-react/package.json +0 -14
package/CHANGELOG.md CHANGED
@@ -1 +1,14 @@
1
- # @atlaskit/editor-statsig-tmp
1
+ # @atlaskit/editor-statsig-tmp
2
+
3
+ ## 1.2.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#131878](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/pull-requests/131878)
8
+ [`705fe39cae267`](https://stash.atlassian.com/projects/CONFCLOUD/repos/confluence-frontend/commits/705fe39cae267) -
9
+ [ED-24597] Update to log `platform_editor_basic_text_transformations` exposure event only for
10
+ users meet all of 3 checks:
11
+
12
+ - Are enrolled to the experiment
13
+ - Have AI disabled
14
+ - Make top level text selection
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.editorExperimentsConfig = void 0;
7
+ function isBoolean(value) {
8
+ return typeof value === 'boolean';
9
+ }
10
+ /**
11
+ * When adding a new experiment, you need to add it here.
12
+ * Please follow the pattern established in the examples and any
13
+ * existing experiments.
14
+ */
15
+ var editorExperimentsConfig = exports.editorExperimentsConfig = {
16
+ // Added 2024-08-08
17
+ 'example-boolean': {
18
+ productKeys: {
19
+ confluence: 'confluence_editor_experiment_test_new_package_boolean'
20
+ },
21
+ param: 'isEnabled',
22
+ typeGuard: isBoolean,
23
+ // Note -- you need to set the type to boolean for the default value
24
+ defaultValue: false
25
+ },
26
+ // Added 2024-08-08
27
+ 'example-multivariate': {
28
+ productKeys: {
29
+ confluence: 'confluence_editor_experiment_test_new_package_multivariate'
30
+ },
31
+ param: 'variant',
32
+ typeGuard: isBoolean,
33
+ // Note -- you need to specify the type of the default value as the union of all possible values
34
+ // This is used to provide type safety on consumption
35
+ defaultValue: 'one'
36
+ },
37
+ // Added 2024-08-08
38
+ 'test-new-experiments-package': {
39
+ productKeys: {
40
+ confluence: 'confluence_editor_experiment_test_new_package',
41
+ jira: 'jira_editor_experiment_test_new_package'
42
+ },
43
+ param: 'isEnabled',
44
+ typeGuard: isBoolean,
45
+ defaultValue: false
46
+ },
47
+ // Add 2024-08-14
48
+ 'basic-text-transformations': {
49
+ productKeys: {
50
+ confluence: 'platform_editor_basic_text_transformations'
51
+ },
52
+ param: 'isEnabled',
53
+ typeGuard: isBoolean,
54
+ defaultValue: false
55
+ }
56
+ };
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.editorExperiment = editorExperiment;
8
+ exports.setupEditorExperiments = setupEditorExperiments;
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
+ var _featureGateJsClient = _interopRequireDefault(require("@atlaskit/feature-gate-js-client"));
12
+ var _experimentsConfig = require("./experiments-config");
13
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
14
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
15
+ var _overrides = {};
16
+ var _product;
17
+
18
+ /**
19
+ * This function is used to set up the editor experiments for testing purposes.
20
+ * It should be called before running code that depends on editor experiments.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * setupEditorExperiments('confluence', {
25
+ * 'experiment-name': 'value',
26
+ * });
27
+ * ```
28
+ */
29
+ function setupEditorExperiments(product,
30
+ /**
31
+ * Overrides are used to set the value of an experiment for testing purposes.
32
+ * This is useful when you want to test a specific value of an experiment.
33
+ */
34
+ overrides) {
35
+ if (overrides) {
36
+ // When setting up overrides, we want to ensure that experiments don't end up with invalid
37
+ // values.
38
+ // For production usage -- this is done via the feature flag client which takes the type
39
+ // and performs equivalent logic.
40
+ // @ts-ignore
41
+ overrides = Object.entries(overrides).reduce(function (acc, _ref) {
42
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 2),
43
+ key = _ref2[0],
44
+ value = _ref2[1];
45
+ var config = _experimentsConfig.editorExperimentsConfig[key];
46
+ acc = _objectSpread(_objectSpread({}, acc), {}, (0, _defineProperty2.default)({}, key, config.typeGuard(value) ? value : config.defaultValue));
47
+ return acc;
48
+ }, {});
49
+ _overrides = overrides;
50
+ }
51
+ _product = product;
52
+ }
53
+
54
+ /**
55
+ * Check the value of an editor experiment.
56
+ *
57
+ * Note: By default this will not fire an [exposure event](https://hello.atlassian.net/wiki/spaces/~732385844/pages/3187295823/Exposure+Events+101).
58
+ *
59
+ * You need explicitly call it using the exposure property when you need an exposure event to be fired (all experiments should fire exposure events).
60
+ *
61
+ * @example Boolean experiment
62
+ * ```ts
63
+ * if (editorExperiment('example-boolean', true)) {
64
+ * // Run code for on variant
65
+ * } else {
66
+ * // Run code for off variant
67
+ * }
68
+ * ```
69
+ *
70
+ * @example Multivariate experiment
71
+ * ```ts
72
+ * switch (true) {
73
+ * case editorExperiment('example-multivariate', 'one'):
74
+ * // Run code for variant one
75
+ * break;
76
+ * case editorExperiment('example-multivariate', 'two'):
77
+ * // Run code for variant two
78
+ * break;
79
+ * case editorExperiment('example-multivariate', 'three'):
80
+ * // Run code for variant three
81
+ * break;
82
+ * }
83
+ * }
84
+ *```
85
+
86
+ @example Experiment with exposure event
87
+ * ```ts
88
+ * // Inside feature surface where either the control or variant should be shown
89
+ * if (editorExperiment('example-boolean', true, { exposure: true })) {
90
+ * // Run code for on variant
91
+ * } else {
92
+ * // Run code for off variant
93
+ * }
94
+ * ```
95
+ */
96
+ function editorExperiment(experimentName, expectedExperimentValue) {
97
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
98
+ exposure: false
99
+ };
100
+ var experimentConfig = _experimentsConfig.editorExperimentsConfig[experimentName];
101
+ if (_overrides[experimentName] !== undefined) {
102
+ // This will be hit in the case of a test setting an override
103
+ return _overrides[experimentName] === expectedExperimentValue;
104
+ }
105
+ if (!_product) {
106
+ // This will be hit in the case of a product not having setup the editor experiment tooling
107
+ return experimentConfig.defaultValue === expectedExperimentValue;
108
+ }
109
+
110
+ // Typescript is complaining here about accessing the productKeys property
111
+ var experimentKey = experimentConfig.productKeys[_product];
112
+ if (!experimentKey) {
113
+ // This will be hit in the case of an experiment not being set up for the product
114
+ return _experimentsConfig.editorExperimentsConfig[experimentName].defaultValue === expectedExperimentValue;
115
+ }
116
+ var experimentValue = _featureGateJsClient.default.getExperimentValue(
117
+ // @ts-ignore
118
+ experimentKey, experimentConfig.param, experimentConfig.defaultValue, {
119
+ typeGuard: experimentConfig.typeGuard,
120
+ fireExperimentExposure: options.exposure
121
+ });
122
+ return expectedExperimentValue === experimentValue;
123
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.eeTest = eeTest;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
10
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
11
+ var _experiments = require("./experiments");
12
+ var _experimentsConfig = require("./experiments-config");
13
+ // This is loosely based on the `ffTest` util from `@atlassian/feature-flags-test-utils` package.
14
+
15
+ /**
16
+ * This is a utility function for testing editor experiments.
17
+ *
18
+ * @example Boolean experiment
19
+ * ```ts
20
+ * eeTest('example-boolean', {
21
+ * true: () => {
22
+ * expect(editorExperiment('example-boolean', true)).toBe(true);
23
+ * expect(editorExperiment('example-boolean', false)).toBe(false);
24
+ * },
25
+ * false: () => {
26
+ * expect(editorExperiment('example-boolean', false)).toBe(true);
27
+ * expect(editorExperiment('example-boolean', true)).toBe(false);
28
+ * },
29
+ * })
30
+ * ```
31
+ *
32
+ * @example Multivariate experiment
33
+ * ```ts
34
+ * eeTest('example-multivariate', {
35
+ * one: () => {
36
+ * expect(editorExperiment('example-multivariate', 'one')).toBe(true);
37
+ * expect(editorExperiment('example-multivariate', 'two')).toBe(false);
38
+ * },
39
+ * two: () => {
40
+ * expect(editorExperiment('example-multivariate', 'two')).toBe(true);
41
+ * expect(editorExperiment('example-multivariate', 'one')).toBe(false);
42
+ * },
43
+ * three: () => {
44
+ * expect(editorExperiment('example-multivariate', 'three')).toBe(true);
45
+ * expect(editorExperiment('example-multivariate', 'one')).toBe(false);
46
+ * },
47
+ * })
48
+ * ```
49
+ */
50
+ function eeTest(experimentName, cases, otherExperiments) {
51
+ (0, _experiments.setupEditorExperiments)('test', {});
52
+ describe("eeTest: ".concat(experimentName), function () {
53
+ afterEach(function () {
54
+ (0, _experiments.setupEditorExperiments)('test', otherExperiments !== null && otherExperiments !== void 0 ? otherExperiments : {});
55
+ });
56
+ var isBooleanExperiment = typeof _experimentsConfig.editorExperimentsConfig[experimentName].defaultValue === 'boolean';
57
+ if (isBooleanExperiment && Object.keys(cases).length !== 2) {
58
+ throw new Error("Expected exactly 2 cases for boolean experiment ".concat(experimentName, ", got ").concat(Object.keys(cases).length));
59
+ }
60
+ test.each(Object.keys(cases))("".concat(experimentName, ": %s"), /*#__PURE__*/function () {
61
+ var _ref = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(value) {
62
+ var testCaseKey, convertedValue, testCase;
63
+ return _regenerator.default.wrap(function _callee$(_context) {
64
+ while (1) switch (_context.prev = _context.next) {
65
+ case 0:
66
+ testCaseKey = value; // For boolean experiments, we need to convert the 'on' and 'off' cases to boolean `true` and `false` values.
67
+ convertedValue = isBooleanExperiment ? testCaseKey === 'true' ? true : false : testCaseKey;
68
+ (0, _experiments.setupEditorExperiments)('test', (0, _defineProperty2.default)({}, experimentName, convertedValue));
69
+ testCase = cases[testCaseKey]; // @ts-ignore
70
+ _context.next = 6;
71
+ return Promise.resolve(testCase());
72
+ case 6:
73
+ case "end":
74
+ return _context.stop();
75
+ }
76
+ }, _callee);
77
+ }));
78
+ return function (_x) {
79
+ return _ref.apply(this, arguments);
80
+ };
81
+ }());
82
+ });
83
+ }
@@ -0,0 +1,50 @@
1
+ function isBoolean(value) {
2
+ return typeof value === 'boolean';
3
+ }
4
+ /**
5
+ * When adding a new experiment, you need to add it here.
6
+ * Please follow the pattern established in the examples and any
7
+ * existing experiments.
8
+ */
9
+ export const editorExperimentsConfig = {
10
+ // Added 2024-08-08
11
+ 'example-boolean': {
12
+ productKeys: {
13
+ confluence: 'confluence_editor_experiment_test_new_package_boolean'
14
+ },
15
+ param: 'isEnabled',
16
+ typeGuard: isBoolean,
17
+ // Note -- you need to set the type to boolean for the default value
18
+ defaultValue: false
19
+ },
20
+ // Added 2024-08-08
21
+ 'example-multivariate': {
22
+ productKeys: {
23
+ confluence: 'confluence_editor_experiment_test_new_package_multivariate'
24
+ },
25
+ param: 'variant',
26
+ typeGuard: isBoolean,
27
+ // Note -- you need to specify the type of the default value as the union of all possible values
28
+ // This is used to provide type safety on consumption
29
+ defaultValue: 'one'
30
+ },
31
+ // Added 2024-08-08
32
+ 'test-new-experiments-package': {
33
+ productKeys: {
34
+ confluence: 'confluence_editor_experiment_test_new_package',
35
+ jira: 'jira_editor_experiment_test_new_package'
36
+ },
37
+ param: 'isEnabled',
38
+ typeGuard: isBoolean,
39
+ defaultValue: false
40
+ },
41
+ // Add 2024-08-14
42
+ 'basic-text-transformations': {
43
+ productKeys: {
44
+ confluence: 'platform_editor_basic_text_transformations'
45
+ },
46
+ param: 'isEnabled',
47
+ typeGuard: isBoolean,
48
+ defaultValue: false
49
+ }
50
+ };
@@ -0,0 +1,110 @@
1
+ import FeatureGates from '@atlaskit/feature-gate-js-client';
2
+ import { editorExperimentsConfig } from './experiments-config';
3
+ let _overrides = {};
4
+ let _product;
5
+
6
+ /**
7
+ * This function is used to set up the editor experiments for testing purposes.
8
+ * It should be called before running code that depends on editor experiments.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * setupEditorExperiments('confluence', {
13
+ * 'experiment-name': 'value',
14
+ * });
15
+ * ```
16
+ */
17
+ export function setupEditorExperiments(product,
18
+ /**
19
+ * Overrides are used to set the value of an experiment for testing purposes.
20
+ * This is useful when you want to test a specific value of an experiment.
21
+ */
22
+ overrides) {
23
+ if (overrides) {
24
+ // When setting up overrides, we want to ensure that experiments don't end up with invalid
25
+ // values.
26
+ // For production usage -- this is done via the feature flag client which takes the type
27
+ // and performs equivalent logic.
28
+ // @ts-ignore
29
+ overrides = Object.entries(overrides).reduce((acc, [key, value]) => {
30
+ const config = editorExperimentsConfig[key];
31
+ acc = {
32
+ ...acc,
33
+ [key]: config.typeGuard(value) ? value : config.defaultValue
34
+ };
35
+ return acc;
36
+ }, {});
37
+ _overrides = overrides;
38
+ }
39
+ _product = product;
40
+ }
41
+
42
+ /**
43
+ * Check the value of an editor experiment.
44
+ *
45
+ * Note: By default this will not fire an [exposure event](https://hello.atlassian.net/wiki/spaces/~732385844/pages/3187295823/Exposure+Events+101).
46
+ *
47
+ * You need explicitly call it using the exposure property when you need an exposure event to be fired (all experiments should fire exposure events).
48
+ *
49
+ * @example Boolean experiment
50
+ * ```ts
51
+ * if (editorExperiment('example-boolean', true)) {
52
+ * // Run code for on variant
53
+ * } else {
54
+ * // Run code for off variant
55
+ * }
56
+ * ```
57
+ *
58
+ * @example Multivariate experiment
59
+ * ```ts
60
+ * switch (true) {
61
+ * case editorExperiment('example-multivariate', 'one'):
62
+ * // Run code for variant one
63
+ * break;
64
+ * case editorExperiment('example-multivariate', 'two'):
65
+ * // Run code for variant two
66
+ * break;
67
+ * case editorExperiment('example-multivariate', 'three'):
68
+ * // Run code for variant three
69
+ * break;
70
+ * }
71
+ * }
72
+ *```
73
+
74
+ @example Experiment with exposure event
75
+ * ```ts
76
+ * // Inside feature surface where either the control or variant should be shown
77
+ * if (editorExperiment('example-boolean', true, { exposure: true })) {
78
+ * // Run code for on variant
79
+ * } else {
80
+ * // Run code for off variant
81
+ * }
82
+ * ```
83
+ */
84
+ export function editorExperiment(experimentName, expectedExperimentValue, options = {
85
+ exposure: false
86
+ }) {
87
+ const experimentConfig = editorExperimentsConfig[experimentName];
88
+ if (_overrides[experimentName] !== undefined) {
89
+ // This will be hit in the case of a test setting an override
90
+ return _overrides[experimentName] === expectedExperimentValue;
91
+ }
92
+ if (!_product) {
93
+ // This will be hit in the case of a product not having setup the editor experiment tooling
94
+ return experimentConfig.defaultValue === expectedExperimentValue;
95
+ }
96
+
97
+ // Typescript is complaining here about accessing the productKeys property
98
+ const experimentKey = experimentConfig.productKeys[_product];
99
+ if (!experimentKey) {
100
+ // This will be hit in the case of an experiment not being set up for the product
101
+ return editorExperimentsConfig[experimentName].defaultValue === expectedExperimentValue;
102
+ }
103
+ const experimentValue = FeatureGates.getExperimentValue(
104
+ // @ts-ignore
105
+ experimentKey, experimentConfig.param, experimentConfig.defaultValue, {
106
+ typeGuard: experimentConfig.typeGuard,
107
+ fireExperimentExposure: options.exposure
108
+ });
109
+ return expectedExperimentValue === experimentValue;
110
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,65 @@
1
+ // This is loosely based on the `ffTest` util from `@atlassian/feature-flags-test-utils` package.
2
+
3
+ import { setupEditorExperiments } from './experiments';
4
+ import { editorExperimentsConfig } from './experiments-config';
5
+
6
+ /**
7
+ * This is a utility function for testing editor experiments.
8
+ *
9
+ * @example Boolean experiment
10
+ * ```ts
11
+ * eeTest('example-boolean', {
12
+ * true: () => {
13
+ * expect(editorExperiment('example-boolean', true)).toBe(true);
14
+ * expect(editorExperiment('example-boolean', false)).toBe(false);
15
+ * },
16
+ * false: () => {
17
+ * expect(editorExperiment('example-boolean', false)).toBe(true);
18
+ * expect(editorExperiment('example-boolean', true)).toBe(false);
19
+ * },
20
+ * })
21
+ * ```
22
+ *
23
+ * @example Multivariate experiment
24
+ * ```ts
25
+ * eeTest('example-multivariate', {
26
+ * one: () => {
27
+ * expect(editorExperiment('example-multivariate', 'one')).toBe(true);
28
+ * expect(editorExperiment('example-multivariate', 'two')).toBe(false);
29
+ * },
30
+ * two: () => {
31
+ * expect(editorExperiment('example-multivariate', 'two')).toBe(true);
32
+ * expect(editorExperiment('example-multivariate', 'one')).toBe(false);
33
+ * },
34
+ * three: () => {
35
+ * expect(editorExperiment('example-multivariate', 'three')).toBe(true);
36
+ * expect(editorExperiment('example-multivariate', 'one')).toBe(false);
37
+ * },
38
+ * })
39
+ * ```
40
+ */
41
+ export function eeTest(experimentName, cases, otherExperiments) {
42
+ setupEditorExperiments('test', {});
43
+ describe(`eeTest: ${experimentName}`, () => {
44
+ afterEach(() => {
45
+ setupEditorExperiments('test', otherExperiments !== null && otherExperiments !== void 0 ? otherExperiments : {});
46
+ });
47
+ const isBooleanExperiment = typeof editorExperimentsConfig[experimentName].defaultValue === 'boolean';
48
+ if (isBooleanExperiment && Object.keys(cases).length !== 2) {
49
+ throw new Error(`Expected exactly 2 cases for boolean experiment ${experimentName}, got ${Object.keys(cases).length}`);
50
+ }
51
+ test.each(Object.keys(cases))(`${experimentName}: %s`, async value => {
52
+ const testCaseKey = value;
53
+
54
+ // For boolean experiments, we need to convert the 'on' and 'off' cases to boolean `true` and `false` values.
55
+ const convertedValue = isBooleanExperiment ? testCaseKey === 'true' ? true : false : testCaseKey;
56
+ setupEditorExperiments('test', {
57
+ [experimentName]: convertedValue
58
+ });
59
+ const testCase = cases[testCaseKey];
60
+
61
+ // @ts-ignore
62
+ await Promise.resolve(testCase());
63
+ });
64
+ });
65
+ }
@@ -0,0 +1,50 @@
1
+ function isBoolean(value) {
2
+ return typeof value === 'boolean';
3
+ }
4
+ /**
5
+ * When adding a new experiment, you need to add it here.
6
+ * Please follow the pattern established in the examples and any
7
+ * existing experiments.
8
+ */
9
+ export var editorExperimentsConfig = {
10
+ // Added 2024-08-08
11
+ 'example-boolean': {
12
+ productKeys: {
13
+ confluence: 'confluence_editor_experiment_test_new_package_boolean'
14
+ },
15
+ param: 'isEnabled',
16
+ typeGuard: isBoolean,
17
+ // Note -- you need to set the type to boolean for the default value
18
+ defaultValue: false
19
+ },
20
+ // Added 2024-08-08
21
+ 'example-multivariate': {
22
+ productKeys: {
23
+ confluence: 'confluence_editor_experiment_test_new_package_multivariate'
24
+ },
25
+ param: 'variant',
26
+ typeGuard: isBoolean,
27
+ // Note -- you need to specify the type of the default value as the union of all possible values
28
+ // This is used to provide type safety on consumption
29
+ defaultValue: 'one'
30
+ },
31
+ // Added 2024-08-08
32
+ 'test-new-experiments-package': {
33
+ productKeys: {
34
+ confluence: 'confluence_editor_experiment_test_new_package',
35
+ jira: 'jira_editor_experiment_test_new_package'
36
+ },
37
+ param: 'isEnabled',
38
+ typeGuard: isBoolean,
39
+ defaultValue: false
40
+ },
41
+ // Add 2024-08-14
42
+ 'basic-text-transformations': {
43
+ productKeys: {
44
+ confluence: 'platform_editor_basic_text_transformations'
45
+ },
46
+ param: 'isEnabled',
47
+ typeGuard: isBoolean,
48
+ defaultValue: false
49
+ }
50
+ };
@@ -0,0 +1,115 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
4
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
5
+ import FeatureGates from '@atlaskit/feature-gate-js-client';
6
+ import { editorExperimentsConfig } from './experiments-config';
7
+ var _overrides = {};
8
+ var _product;
9
+
10
+ /**
11
+ * This function is used to set up the editor experiments for testing purposes.
12
+ * It should be called before running code that depends on editor experiments.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * setupEditorExperiments('confluence', {
17
+ * 'experiment-name': 'value',
18
+ * });
19
+ * ```
20
+ */
21
+ export function setupEditorExperiments(product,
22
+ /**
23
+ * Overrides are used to set the value of an experiment for testing purposes.
24
+ * This is useful when you want to test a specific value of an experiment.
25
+ */
26
+ overrides) {
27
+ if (overrides) {
28
+ // When setting up overrides, we want to ensure that experiments don't end up with invalid
29
+ // values.
30
+ // For production usage -- this is done via the feature flag client which takes the type
31
+ // and performs equivalent logic.
32
+ // @ts-ignore
33
+ overrides = Object.entries(overrides).reduce(function (acc, _ref) {
34
+ var _ref2 = _slicedToArray(_ref, 2),
35
+ key = _ref2[0],
36
+ value = _ref2[1];
37
+ var config = editorExperimentsConfig[key];
38
+ acc = _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, config.typeGuard(value) ? value : config.defaultValue));
39
+ return acc;
40
+ }, {});
41
+ _overrides = overrides;
42
+ }
43
+ _product = product;
44
+ }
45
+
46
+ /**
47
+ * Check the value of an editor experiment.
48
+ *
49
+ * Note: By default this will not fire an [exposure event](https://hello.atlassian.net/wiki/spaces/~732385844/pages/3187295823/Exposure+Events+101).
50
+ *
51
+ * You need explicitly call it using the exposure property when you need an exposure event to be fired (all experiments should fire exposure events).
52
+ *
53
+ * @example Boolean experiment
54
+ * ```ts
55
+ * if (editorExperiment('example-boolean', true)) {
56
+ * // Run code for on variant
57
+ * } else {
58
+ * // Run code for off variant
59
+ * }
60
+ * ```
61
+ *
62
+ * @example Multivariate experiment
63
+ * ```ts
64
+ * switch (true) {
65
+ * case editorExperiment('example-multivariate', 'one'):
66
+ * // Run code for variant one
67
+ * break;
68
+ * case editorExperiment('example-multivariate', 'two'):
69
+ * // Run code for variant two
70
+ * break;
71
+ * case editorExperiment('example-multivariate', 'three'):
72
+ * // Run code for variant three
73
+ * break;
74
+ * }
75
+ * }
76
+ *```
77
+
78
+ @example Experiment with exposure event
79
+ * ```ts
80
+ * // Inside feature surface where either the control or variant should be shown
81
+ * if (editorExperiment('example-boolean', true, { exposure: true })) {
82
+ * // Run code for on variant
83
+ * } else {
84
+ * // Run code for off variant
85
+ * }
86
+ * ```
87
+ */
88
+ export function editorExperiment(experimentName, expectedExperimentValue) {
89
+ var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
90
+ exposure: false
91
+ };
92
+ var experimentConfig = editorExperimentsConfig[experimentName];
93
+ if (_overrides[experimentName] !== undefined) {
94
+ // This will be hit in the case of a test setting an override
95
+ return _overrides[experimentName] === expectedExperimentValue;
96
+ }
97
+ if (!_product) {
98
+ // This will be hit in the case of a product not having setup the editor experiment tooling
99
+ return experimentConfig.defaultValue === expectedExperimentValue;
100
+ }
101
+
102
+ // Typescript is complaining here about accessing the productKeys property
103
+ var experimentKey = experimentConfig.productKeys[_product];
104
+ if (!experimentKey) {
105
+ // This will be hit in the case of an experiment not being set up for the product
106
+ return editorExperimentsConfig[experimentName].defaultValue === expectedExperimentValue;
107
+ }
108
+ var experimentValue = FeatureGates.getExperimentValue(
109
+ // @ts-ignore
110
+ experimentKey, experimentConfig.param, experimentConfig.defaultValue, {
111
+ typeGuard: experimentConfig.typeGuard,
112
+ fireExperimentExposure: options.exposure
113
+ });
114
+ return expectedExperimentValue === experimentValue;
115
+ }
@@ -0,0 +1 @@
1
+ export {};