@configura/web-api 1.6.0-iotest.2 → 1.6.1-alpha.1

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 (43) hide show
  1. package/dist/CfgProduct.d.ts +29 -10
  2. package/dist/CfgProduct.js +82 -47
  3. package/dist/index.d.ts +2 -4
  4. package/dist/index.js +2 -4
  5. package/dist/productConfiguration/CfgFeature.d.ts +2 -1
  6. package/dist/productConfiguration/CfgFeature.js +27 -8
  7. package/dist/productConfiguration/CfgOption.d.ts +21 -8
  8. package/dist/productConfiguration/CfgOption.js +26 -18
  9. package/dist/productConfiguration/CfgProductConfiguration.d.ts +1 -2
  10. package/dist/productConfiguration/CfgProductConfiguration.js +9 -8
  11. package/dist/syncGroups/SyncGroupsApplier.d.ts +20 -0
  12. package/dist/syncGroups/SyncGroupsApplier.js +520 -0
  13. package/dist/syncGroups/SyncGroupsApplyMode.d.ts +21 -0
  14. package/dist/syncGroups/SyncGroupsApplyMode.js +21 -0
  15. package/dist/syncGroups/SyncGroupsHandler.d.ts +31 -0
  16. package/dist/syncGroups/SyncGroupsHandler.js +71 -0
  17. package/dist/syncGroups/SyncGroupsPathHelper.d.ts +27 -0
  18. package/dist/syncGroups/SyncGroupsPathHelper.js +89 -0
  19. package/dist/syncGroups/SyncGroupsState.d.ts +20 -0
  20. package/dist/syncGroups/SyncGroupsState.js +108 -0
  21. package/dist/syncGroups/SyncGroupsTransaction.d.ts +51 -0
  22. package/dist/syncGroups/SyncGroupsTransaction.js +100 -0
  23. package/dist/tests/testData/testDataAdditionalProductInAdditionalProductInProductForTest.js +24 -95
  24. package/dist/tests/testData/testDataCachedGetProduct.js +8 -19
  25. package/dist/tests/testData/testDataOptions.d.ts +13 -0
  26. package/dist/tests/testData/testDataOptions.js +60 -0
  27. package/dist/tests/testData/testDataProductAggregatedPrice.js +12 -23
  28. package/dist/tests/testData/testDataUpcharge.js +16 -48
  29. package/dist/utilitiesCatalogueData.d.ts +7 -1
  30. package/dist/utilitiesCatalogueData.js +105 -4
  31. package/package.json +3 -3
  32. package/dist/io/CfgHistoryManager.d.ts +0 -30
  33. package/dist/io/CfgHistoryManager.js +0 -62
  34. package/dist/io/CfgHistoryToProdConfConnector.d.ts +0 -10
  35. package/dist/io/CfgHistoryToProdConfConnector.js +0 -20
  36. package/dist/io/CfgIOManager.d.ts +0 -29
  37. package/dist/io/CfgIOManager.js +0 -89
  38. package/dist/io/CfgIOProdConfConnector.d.ts +0 -33
  39. package/dist/io/CfgIOProdConfConnector.js +0 -100
  40. package/dist/io/CfgWindowMessageManager.d.ts +0 -13
  41. package/dist/io/CfgWindowMessageManager.js +0 -28
  42. package/dist/io/CfgWindowMessageToProdConfConnector.d.ts +0 -13
  43. package/dist/io/CfgWindowMessageToProdConfConnector.js +0 -17
@@ -0,0 +1,27 @@
1
+ import { _CfgProductInternal } from "../CfgProduct.js";
2
+ import { _CfgFeatureInternal } from "../productConfiguration/CfgFeature.js";
3
+ import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
4
+ import { _CfgProductConfigurationInternal } from "../productConfiguration/CfgProductConfiguration.js";
5
+ export declare type CfgPathSegment = string;
6
+ /**
7
+ * Represents the path to a node in the configuration tree.
8
+ *
9
+ * The format consists of a number of CfgPathSegments, each of which is currently a string. The
10
+ * exact meaning of the strings vary depending on where they are located in the path.
11
+ *
12
+ * @warning
13
+ * The format is strictly internal and can change in later versions of the SDK.
14
+ * Data stored in a CfgPath should be thus be considered transient and never stored or transmitted.
15
+ */
16
+ export declare type CfgPath = CfgPathSegment[];
17
+ declare type PathItemType = _CfgProductInternal | _CfgProductConfigurationInternal | _CfgFeatureInternal | _CfgOptionInternal;
18
+ export declare class SyncGroupsPathHelper {
19
+ static getPath(item: PathItemType): CfgPath;
20
+ static getFromPath(path: CfgPath, root: PathItemType): PathItemType;
21
+ static getProductFromPath(path: CfgPath, item: _CfgProductInternal): _CfgProductInternal;
22
+ static getProductConfigurationFromPath(path: CfgPath, item: _CfgProductInternal): _CfgProductConfigurationInternal;
23
+ static getFeatureFromPath(path: CfgPath, item: PathItemType): _CfgFeatureInternal;
24
+ static getOptionFromPath(path: CfgPath, item: PathItemType): _CfgOptionInternal;
25
+ }
26
+ export {};
27
+ //# sourceMappingURL=SyncGroupsPathHelper.d.ts.map
@@ -0,0 +1,89 @@
1
+ import { assert, assertDefined } from "@configura/web-utilities";
2
+ import { _CfgProductInternal } from "../CfgProduct.js";
3
+ import { _CfgFeatureInternal } from "../productConfiguration/CfgFeature.js";
4
+ import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
5
+ import { _CfgProductConfigurationInternal } from "../productConfiguration/CfgProductConfiguration.js";
6
+ export class SyncGroupsPathHelper {
7
+ static getPath(item) {
8
+ if (item instanceof _CfgProductInternal) {
9
+ const parent = item.parent;
10
+ const refKey = item.refKey;
11
+ if (parent === undefined || refKey === undefined) {
12
+ return [];
13
+ }
14
+ return [...this.getPath(parent), "p", refKey];
15
+ }
16
+ if (item instanceof _CfgProductConfigurationInternal) {
17
+ return [...this.getPath(item.parentProduct), "c"];
18
+ }
19
+ if (item instanceof _CfgFeatureInternal) {
20
+ return [...this.getPath(item.parent), item.code];
21
+ }
22
+ if (item instanceof _CfgOptionInternal) {
23
+ return [...this.getPath(item.parent), item.code];
24
+ }
25
+ throw new Error("This should not happen");
26
+ }
27
+ static getFromPath(path, root) {
28
+ path = path.slice();
29
+ let item = root;
30
+ while (path.length > 0) {
31
+ const segment = path.shift();
32
+ if (item instanceof _CfgProductInternal) {
33
+ switch (segment) {
34
+ case "p":
35
+ const refKey = path.shift();
36
+ const additional = item.additionalProducts.find((p) => p.refKey === refKey);
37
+ assertDefined(additional, `Additional product not found "p, ${refKey}, ${path.join(", ")}"`);
38
+ item = additional._internal;
39
+ break;
40
+ case "c":
41
+ assert(item instanceof _CfgProductInternal, "Was not product");
42
+ item = item.configuration._internal;
43
+ break;
44
+ default:
45
+ throw new Error(`Unexpected path segment ${segment}`);
46
+ }
47
+ }
48
+ else if (item instanceof _CfgProductConfigurationInternal) {
49
+ const feature = item.features.find((f) => f.code === segment);
50
+ assertDefined(feature, `Feature not found ${segment}, ${path.join(", ")}`);
51
+ item = feature._internal;
52
+ }
53
+ else if (item instanceof _CfgFeatureInternal) {
54
+ const option = item.options.find((o) => o.code === segment);
55
+ assertDefined(option, `Option not found ${segment}, ${path.join(", ")}`);
56
+ item = option._internal;
57
+ }
58
+ else if (item instanceof _CfgOptionInternal) {
59
+ const feature = item.features.find((o) => o.code === segment);
60
+ assertDefined(feature, `Feature not found ${segment}, ${path.join(", ")}`);
61
+ item = feature._internal;
62
+ }
63
+ else {
64
+ throw new Error("This should not happen (unexpected type)");
65
+ }
66
+ }
67
+ return item;
68
+ }
69
+ static getProductFromPath(path, item) {
70
+ const p = this.getFromPath(path, item);
71
+ assert(p instanceof _CfgProductInternal, `Path did not lead to a Product`);
72
+ return p;
73
+ }
74
+ static getProductConfigurationFromPath(path, item) {
75
+ const c = this.getFromPath(path, item);
76
+ assert(c instanceof _CfgProductConfigurationInternal, `Path did not lead to a ProductConfiguration"`);
77
+ return c;
78
+ }
79
+ static getFeatureFromPath(path, item) {
80
+ const f = this.getFromPath(path, item);
81
+ assert(f instanceof _CfgFeatureInternal, `Path did not lead to a Feature`);
82
+ return f;
83
+ }
84
+ static getOptionFromPath(path, item) {
85
+ const o = this.getFromPath(path, item);
86
+ assert(o instanceof _CfgOptionInternal, `Path did not lead to a Option`);
87
+ return o;
88
+ }
89
+ }
@@ -0,0 +1,20 @@
1
+ import { OptionCode, SyncCode } from "./SyncGroupsHandler.js";
2
+ /**
3
+ * Is used to keep track of the current value of the SyncGroups. Is fully separated between
4
+ * SelectOne and SelectMany as Features of the two types are synced separately.
5
+ */
6
+ export declare class SyncGroupsState {
7
+ readonly _selectOne: Map<SyncCode, OptionCode>;
8
+ readonly _selectMany: Map<SyncCode, Map<OptionCode, boolean>>;
9
+ clone(): SyncGroupsState;
10
+ /**
11
+ * Replaces the current state
12
+ */
13
+ setFrom(other: SyncGroupsState): void;
14
+ setForSelectOne(syncCode: SyncCode, optionCode: OptionCode): void;
15
+ setForSelectMany(syncCode: SyncCode, optionCode: OptionCode, selected: boolean): void;
16
+ getForSelectOne(syncCode: SyncCode): OptionCode | undefined;
17
+ getForSelectMany(syncCode: SyncCode, optionCode: OptionCode): boolean | undefined;
18
+ logDebug(group?: string, code?: string, selected?: boolean): void;
19
+ }
20
+ //# sourceMappingURL=SyncGroupsState.d.ts.map
@@ -0,0 +1,108 @@
1
+ /**
2
+ * Is used to keep track of the current value of the SyncGroups. Is fully separated between
3
+ * SelectOne and SelectMany as Features of the two types are synced separately.
4
+ */
5
+ export class SyncGroupsState {
6
+ constructor() {
7
+ this._selectOne = new Map();
8
+ this._selectMany = new Map();
9
+ }
10
+ clone() {
11
+ const result = new SyncGroupsState();
12
+ result.setFrom(this);
13
+ return result;
14
+ }
15
+ /**
16
+ * Replaces the current state
17
+ */
18
+ setFrom(other) {
19
+ this._selectOne.clear();
20
+ this._selectMany.clear();
21
+ for (const [k, v] of other._selectOne) {
22
+ this._selectOne.set(k, v);
23
+ }
24
+ for (const [sourceSyncCode, sourceOptionToSelected] of other._selectMany) {
25
+ const targetOptionToSelected = new Map();
26
+ for (const [sourceOptionCode, sourceIsSelected] of sourceOptionToSelected) {
27
+ targetOptionToSelected.set(sourceOptionCode, sourceIsSelected);
28
+ }
29
+ this._selectMany.set(sourceSyncCode, targetOptionToSelected);
30
+ }
31
+ }
32
+ setForSelectOne(syncCode, optionCode) {
33
+ this._selectOne.set(syncCode, optionCode);
34
+ this.logDebug(syncCode, optionCode);
35
+ }
36
+ setForSelectMany(syncCode, optionCode, selected) {
37
+ let forSyncCode = this._selectMany.get(syncCode);
38
+ if (forSyncCode === undefined) {
39
+ forSyncCode = new Map();
40
+ this._selectMany.set(syncCode, forSyncCode);
41
+ }
42
+ forSyncCode.set(optionCode, selected);
43
+ this.logDebug(syncCode, optionCode, selected);
44
+ }
45
+ getForSelectOne(syncCode) {
46
+ return this._selectOne.get(syncCode);
47
+ }
48
+ getForSelectMany(syncCode, optionCode) {
49
+ var _a;
50
+ return (_a = this._selectMany.get(syncCode)) === null || _a === void 0 ? void 0 : _a.get(optionCode);
51
+ }
52
+ logDebug(group, code, selected) {
53
+ const isMany = selected !== undefined;
54
+ const selectOne = Array.from(this._selectOne.entries());
55
+ const selectMany = Array.from(this._selectMany.entries()).reduce((a, [groupCode, optionCodeToSelected]) => {
56
+ for (const [optionCode, selected] of optionCodeToSelected) {
57
+ a.push([groupCode, optionCode, selected]);
58
+ }
59
+ return a;
60
+ }, []);
61
+ let columnWidth = 1;
62
+ selectOne.forEach((e) => {
63
+ columnWidth = Math.max(columnWidth, e[0].length);
64
+ });
65
+ selectMany.forEach((e) => {
66
+ columnWidth = Math.max(columnWidth, e[0].length);
67
+ });
68
+ const padding = Array(columnWidth).join(" ");
69
+ const styleBold = "font-weight: bold";
70
+ const styleBoldThis = "color:blue; font-weight: bold";
71
+ const styleBoldOn = "color:green; font-weight: bold";
72
+ const styleBoldOff = "color:red; font-weight: bold";
73
+ const styleThis = "color:blue";
74
+ const styleOn = "color:green";
75
+ const styleOff = "color:red";
76
+ const output = [];
77
+ if (group === undefined) {
78
+ output.push("");
79
+ }
80
+ else if (isMany) {
81
+ output.push(...[
82
+ `%c${code} %cin %c${group} %cset to %c${selected ? "on" : "off"}\n`,
83
+ styleBoldThis,
84
+ "",
85
+ styleBoldThis,
86
+ "",
87
+ selected ? styleBoldOn : styleBoldOff,
88
+ ]);
89
+ }
90
+ else {
91
+ output.push(...[`%c${group}%c set to %c${code}\n`, styleBoldThis, "", styleBoldThis]);
92
+ }
93
+ output[0] = output[0] + "%cSync State (single)";
94
+ output.push(styleBold);
95
+ selectOne.forEach((e) => {
96
+ output[0] = output[0] + `\n %c${(padding + e[0]).slice(-columnWidth)}: ${e[1]}`;
97
+ output.push(!isMany && group === e[0] ? styleThis : "");
98
+ });
99
+ output[0] = output[0] + "\n%cSync State (multi)";
100
+ output.push(styleBold);
101
+ selectMany.forEach((e) => {
102
+ output[0] = output[0] + `\n %c${(padding + e[0]).slice(-columnWidth)}: %c${e[1]}`;
103
+ output.push(isMany && group === e[0] ? styleThis : "");
104
+ output.push(e[2] === true ? styleOn : styleOff);
105
+ });
106
+ console.log(...output);
107
+ }
108
+ }
@@ -0,0 +1,51 @@
1
+ import { _CfgProductInternal } from "../CfgProduct.js";
2
+ import { _CfgFeatureInternal } from "../productConfiguration/CfgFeature.js";
3
+ import { _CfgOptionInternal } from "../productConfiguration/CfgOption.js";
4
+ import { ProductLoader } from "../productLoader.js";
5
+ import { SyncGroupsApplyMode } from "./SyncGroupsApplyMode.js";
6
+ import { OptionCode, SyncCode } from "./SyncGroupsHandler.js";
7
+ import { CfgPath } from "./SyncGroupsPathHelper.js";
8
+ import { SyncGroupsState } from "./SyncGroupsState.js";
9
+ /**
10
+ * A transaction is normally limited to one user interaction. Like opening a product or
11
+ * selecting an option. This object is used to keep data for one transaction. In particular
12
+ * what Features and what SyncGroups have been affected in the transaction. This is a means
13
+ * to eliminate the risk of infinite loops.
14
+ */
15
+ export declare class SyncGroupsTransaction {
16
+ readonly syncState: SyncGroupsState;
17
+ readonly updateMode: SyncGroupsApplyMode;
18
+ readonly productLoader: ProductLoader;
19
+ readonly original: _CfgProductInternal;
20
+ readonly target: _CfgProductInternal;
21
+ readonly initial: _CfgProductInternal | undefined;
22
+ static make(syncState: SyncGroupsState, updateMode: SyncGroupsApplyMode, product: _CfgProductInternal, productLoader: ProductLoader, assumeNoStartState: boolean): Promise<SyncGroupsTransaction>;
23
+ /**
24
+ *
25
+ * @param syncState A clone of the original syncState. Replaces the original syncState if nothing fails and the transaction doesn't get aborted
26
+ * @param updateMode
27
+ * @param productLoader
28
+ * @param original The product instance that this transaction will be applied on provided nothing fails and the transaction doesn't get aborted
29
+ * @param target A clone of the original product used to apply the configuration changes to
30
+ * @param initial A clone of the original product used to track what the original state was. As a safe measure we do not use originalProduct for this, as it might be changed by someone else
31
+ */
32
+ private constructor();
33
+ private _aborted;
34
+ private affectedSelectOneFeatures;
35
+ private affectedSelectManyOptions;
36
+ private affectedSelectOneSyncGroups;
37
+ private affectedSelectManySyncGroupsAndOptions;
38
+ get isAborted(): boolean;
39
+ abort(): void;
40
+ init(): Promise<boolean>;
41
+ selectOption(optionPath: CfgPath, on: boolean): Promise<boolean>;
42
+ addSelectOneFeatureAffected(feature: _CfgFeatureInternal): void;
43
+ addSelectManyOptionAffected(option: _CfgOptionInternal): void;
44
+ hasSelectOneFeatureBeenAffected(feature: _CfgFeatureInternal): boolean;
45
+ hasSelectManyOptionBeenAffected(option: _CfgOptionInternal): boolean;
46
+ addSyncGroupAffectedForSelectOne(syncCode: SyncCode): void;
47
+ addSyncGroupAffectedForSelectMany(syncCode: SyncCode, optionCode: OptionCode): void;
48
+ isSyncGroupAffectedForSelectOne(syncCode: SyncCode): boolean;
49
+ isSyncGroupAffectedForSelectMany(syncCode: SyncCode, optionCode: OptionCode): boolean;
50
+ }
51
+ //# sourceMappingURL=SyncGroupsTransaction.d.ts.map
@@ -0,0 +1,100 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { assert } from "@configura/web-utilities";
11
+ import { SelectionType } from "../productConfiguration/CfgFeature.js";
12
+ import { SyncGroupsApplier } from "./SyncGroupsApplier.js";
13
+ import { SyncGroupsPathHelper } from "./SyncGroupsPathHelper.js";
14
+ /**
15
+ * A transaction is normally limited to one user interaction. Like opening a product or
16
+ * selecting an option. This object is used to keep data for one transaction. In particular
17
+ * what Features and what SyncGroups have been affected in the transaction. This is a means
18
+ * to eliminate the risk of infinite loops.
19
+ */
20
+ export class SyncGroupsTransaction {
21
+ /**
22
+ *
23
+ * @param syncState A clone of the original syncState. Replaces the original syncState if nothing fails and the transaction doesn't get aborted
24
+ * @param updateMode
25
+ * @param productLoader
26
+ * @param original The product instance that this transaction will be applied on provided nothing fails and the transaction doesn't get aborted
27
+ * @param target A clone of the original product used to apply the configuration changes to
28
+ * @param initial A clone of the original product used to track what the original state was. As a safe measure we do not use originalProduct for this, as it might be changed by someone else
29
+ */
30
+ constructor(syncState, updateMode, productLoader, original, target, initial) {
31
+ this.syncState = syncState;
32
+ this.updateMode = updateMode;
33
+ this.productLoader = productLoader;
34
+ this.original = original;
35
+ this.target = target;
36
+ this.initial = initial;
37
+ this._aborted = false;
38
+ this.affectedSelectOneFeatures = new Set();
39
+ this.affectedSelectManyOptions = new Set();
40
+ this.affectedSelectOneSyncGroups = new Set();
41
+ this.affectedSelectManySyncGroupsAndOptions = new Map();
42
+ }
43
+ static make(syncState, updateMode, product, productLoader, assumeNoStartState) {
44
+ return __awaiter(this, void 0, void 0, function* () {
45
+ const t = new this(syncState.clone(), updateMode, productLoader, product, yield product.clone(), assumeNoStartState ? undefined : yield product.clone());
46
+ return t;
47
+ });
48
+ }
49
+ get isAborted() {
50
+ return this._aborted;
51
+ }
52
+ abort() {
53
+ this._aborted = true;
54
+ }
55
+ init() {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ return yield SyncGroupsApplier.init(this);
58
+ });
59
+ }
60
+ selectOption(optionPath, on) {
61
+ return __awaiter(this, void 0, void 0, function* () {
62
+ const targetOption = SyncGroupsPathHelper.getOptionFromPath(optionPath, this.target);
63
+ return yield SyncGroupsApplier.selectOption(this, targetOption, on);
64
+ });
65
+ }
66
+ addSelectOneFeatureAffected(feature) {
67
+ assert(feature.selectionType === SelectionType.SelectOne, "Can only be used for SelectOne Feature");
68
+ this.affectedSelectOneFeatures.add(feature);
69
+ }
70
+ addSelectManyOptionAffected(option) {
71
+ assert(option.parent.selectionType === SelectionType.SelectMany, "Can only be used for option in SelectMany Feature");
72
+ this.affectedSelectManyOptions.add(option);
73
+ }
74
+ hasSelectOneFeatureBeenAffected(feature) {
75
+ assert(feature.selectionType === SelectionType.SelectOne, "Can only be used for SelectOne Feature");
76
+ return this.affectedSelectOneFeatures.has(feature);
77
+ }
78
+ hasSelectManyOptionBeenAffected(option) {
79
+ assert(option.parent.selectionType === SelectionType.SelectMany, "Can only be used for option in SelectMany Feature");
80
+ return this.affectedSelectManyOptions.has(option);
81
+ }
82
+ addSyncGroupAffectedForSelectOne(syncCode) {
83
+ this.affectedSelectOneSyncGroups.add(syncCode);
84
+ }
85
+ addSyncGroupAffectedForSelectMany(syncCode, optionCode) {
86
+ let forSyncCode = this.affectedSelectManySyncGroupsAndOptions.get(syncCode);
87
+ if (forSyncCode === undefined) {
88
+ forSyncCode = new Set();
89
+ this.affectedSelectManySyncGroupsAndOptions.set(syncCode, forSyncCode);
90
+ }
91
+ forSyncCode.add(optionCode);
92
+ }
93
+ isSyncGroupAffectedForSelectOne(syncCode) {
94
+ return this.affectedSelectOneSyncGroups.has(syncCode);
95
+ }
96
+ isSyncGroupAffectedForSelectMany(syncCode, optionCode) {
97
+ var _a;
98
+ return ((_a = this.affectedSelectManySyncGroupsAndOptions.get(syncCode)) === null || _a === void 0 ? void 0 : _a.has(optionCode)) === true;
99
+ }
100
+ }
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { CfgProduct } from "../../CfgProduct.js";
11
11
  import { Collector } from "./collectorForTest.js";
12
12
  import { dummyCatId } from "./dummyProductForTest.js";
13
+ import { letterOptionCodeA, letterOptionCodeB, letterOptionCodeC, letterOptions, } from "./testDataOptions.js";
13
14
  const A = () => ({
14
15
  uuid: "A",
15
16
  unit: "m",
@@ -19,96 +20,37 @@ const A = () => ({
19
20
  description: "",
20
21
  numericOrder: false,
21
22
  options: [
22
- {
23
- code: "optionA",
24
- description: "",
25
- additionalProductRefs: [
23
+ Object.assign(Object.assign({}, letterOptions[0]), { additionalProductRefs: [
26
24
  { refKey: "C_0", catId: dummyCatId, partNumber: "C" },
27
25
  { refKey: "B_0", catId: dummyCatId, partNumber: "B" },
28
- ],
29
- },
30
- {
31
- code: "optionB",
32
- description: "",
33
- },
34
- {
35
- code: "optionC",
36
- description: "",
37
- additionalProductRefs: [{ refKey: "D", catId: dummyCatId, partNumber: "D" }],
38
- },
26
+ ] }),
27
+ letterOptions[1],
28
+ Object.assign(Object.assign({}, letterOptions[2]), { additionalProductRefs: [{ refKey: "D", catId: dummyCatId, partNumber: "D" }] }),
39
29
  ],
40
30
  },
41
31
  {
42
32
  code: "featureX",
43
33
  description: "",
44
34
  numericOrder: false,
45
- options: [
46
- {
47
- code: "optionA",
48
- description: "",
49
- },
50
- {
51
- code: "optionB",
52
- description: "",
53
- },
54
- {
55
- code: "optionC",
56
- description: "",
57
- },
58
- ],
35
+ options: [...letterOptions],
59
36
  },
60
37
  {
61
38
  code: "featureNotUsed",
62
39
  description: "",
63
40
  numericOrder: false,
64
- options: [
65
- {
66
- code: "optionA",
67
- description: "",
68
- },
69
- {
70
- code: "optionB",
71
- description: "",
72
- },
73
- ],
41
+ options: [...letterOptions],
74
42
  },
75
43
  {
76
44
  code: "featureOptionCSelectedAtStart",
77
45
  description: "",
78
46
  numericOrder: false,
79
- options: [
80
- {
81
- code: "optionA",
82
- description: "",
83
- },
84
- {
85
- code: "optionB",
86
- description: "",
87
- },
88
- {
89
- code: "optionC",
90
- description: "",
91
- },
92
- ],
47
+ options: [...letterOptions],
93
48
  },
94
49
  {
95
50
  code: "featureSelectMany",
96
51
  description: "",
97
52
  numericOrder: false,
98
- options: [
99
- {
100
- code: "optionA",
101
- description: "",
102
- },
103
- {
104
- code: "optionB",
105
- description: "",
106
- },
107
- {
108
- code: "optionC",
109
- description: "",
110
- },
111
- ],
53
+ options: [...letterOptions],
112
54
  },
113
55
  ],
114
56
  productData: {
@@ -123,24 +65,24 @@ const A = () => ({
123
65
  {
124
66
  code: "!~!",
125
67
  next: {
126
- optionA: {
127
- code: "optionA",
68
+ [letterOptionCodeA]: {
69
+ code: letterOptionCodeA,
128
70
  },
129
71
  },
130
72
  },
131
73
  {
132
74
  code: "!~!",
133
75
  next: {
134
- optionB: {
135
- code: "optionB",
76
+ [letterOptionCodeB]: {
77
+ code: letterOptionCodeB,
136
78
  },
137
79
  },
138
80
  },
139
81
  {
140
82
  code: "!~!",
141
83
  next: {
142
- optionC: {
143
- code: "optionC",
84
+ [letterOptionCodeC]: {
85
+ code: letterOptionCodeC,
144
86
  },
145
87
  },
146
88
  },
@@ -219,20 +161,7 @@ const C = () => ({
219
161
  code: "featureC",
220
162
  description: "",
221
163
  numericOrder: false,
222
- options: [
223
- {
224
- code: "optionA",
225
- description: "",
226
- },
227
- {
228
- code: "optionB",
229
- description: "",
230
- },
231
- {
232
- code: "optionC",
233
- description: "",
234
- },
235
- ],
164
+ options: [...letterOptions],
236
165
  },
237
166
  ],
238
167
  productData: {
@@ -246,8 +175,8 @@ const C = () => ({
246
175
  {
247
176
  code: "!~!",
248
177
  next: {
249
- optionA: {
250
- code: "optionA",
178
+ [letterOptionCodeA]: {
179
+ code: letterOptionCodeA,
251
180
  },
252
181
  },
253
182
  },
@@ -297,8 +226,8 @@ export const cfgProductTest = (testFunc, prepFunc) => __awaiter(void 0, void 0,
297
226
  {
298
227
  code: "!~!",
299
228
  next: {
300
- optionC: {
301
- code: "optionC",
229
+ [letterOptionCodeC]: {
230
+ code: letterOptionCodeC,
302
231
  },
303
232
  },
304
233
  },
@@ -307,16 +236,16 @@ export const cfgProductTest = (testFunc, prepFunc) => __awaiter(void 0, void 0,
307
236
  productData.partsData.selOptions.push({
308
237
  code: "!~!",
309
238
  next: {
310
- optionC: {
311
- code: "optionC",
239
+ [letterOptionCodeC]: {
240
+ code: letterOptionCodeC,
312
241
  },
313
242
  },
314
243
  });
315
244
  productData.partsData.selOptions.push({
316
245
  code: "!~!",
317
246
  next: {
318
- optionC: {
319
- code: "optionC",
247
+ [letterOptionCodeC]: {
248
+ code: letterOptionCodeC,
320
249
  },
321
250
  },
322
251
  });
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { CfgProduct } from "../../CfgProduct.js";
11
11
  import { wrapWithGetProductCache } from "../../productLoader.js";
12
12
  import { dummyCatId } from "./dummyProductForTest.js";
13
+ import { letterOptionCodeA, letterOptions } from "./testDataOptions.js";
13
14
  let prodKeyArray = [];
14
15
  const A = () => ({
15
16
  uuid: "A",
@@ -20,24 +21,12 @@ const A = () => ({
20
21
  description: "",
21
22
  numericOrder: false,
22
23
  options: [
23
- {
24
- code: "optionA",
25
- description: "",
26
- additionalProductRefs: [
24
+ Object.assign(Object.assign({}, letterOptions[0]), { additionalProductRefs: [
27
25
  { refKey: "C_0", catId: dummyCatId, partNumber: "C" },
28
26
  { refKey: "B_0", catId: dummyCatId, partNumber: "B" },
29
- ],
30
- },
31
- {
32
- code: "optionB",
33
- description: "",
34
- additionalProductRefs: [{ refKey: "E", catId: dummyCatId, partNumber: "E" }],
35
- },
36
- {
37
- code: "optionC",
38
- description: "",
39
- additionalProductRefs: [{ refKey: "D", catId: dummyCatId, partNumber: "D" }],
40
- },
27
+ ] }),
28
+ Object.assign(Object.assign({}, letterOptions[1]), { additionalProductRefs: [{ refKey: "E", catId: dummyCatId, partNumber: "E" }] }),
29
+ Object.assign(Object.assign({}, letterOptions[2]), { additionalProductRefs: [{ refKey: "D", catId: dummyCatId, partNumber: "D" }] }),
41
30
  ],
42
31
  },
43
32
  ],
@@ -53,8 +42,8 @@ const A = () => ({
53
42
  {
54
43
  code: "!~!",
55
44
  next: {
56
- optionA: {
57
- code: "optionA",
45
+ [letterOptionCodeA]: {
46
+ code: letterOptionCodeA,
58
47
  },
59
48
  },
60
49
  },
@@ -165,7 +154,7 @@ export const cachedProductLoaderTest = () => __awaiter(void 0, void 0, void 0, f
165
154
  getProduct: getTestProduct,
166
155
  postValidate: (params, _body) => __awaiter(void 0, void 0, void 0, function* () {
167
156
  const productData = (yield getTestProduct(params, true)).productData;
168
- let code = "optionA";
157
+ let code = letterOptionCodeA;
169
158
  for (let test in _body.selOptions[0].next) {
170
159
  code = test;
171
160
  break;