@o3r/testing 13.0.0-next.6 → 13.0.0-prerelease.2

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 (129) hide show
  1. package/core/angular/angular-materials/autocomplete-material.js +9 -20
  2. package/core/angular/angular-materials/autocomplete-material.js.map +1 -1
  3. package/core/angular/angular-materials/index.js +1 -1
  4. package/core/angular/angular-materials/select-material.js +42 -91
  5. package/core/angular/angular-materials/select-material.js.map +1 -1
  6. package/core/angular/angular-materials/slider-material.js +8 -11
  7. package/core/angular/angular-materials/slider-material.js.map +1 -1
  8. package/core/angular/component-fixture.js +68 -148
  9. package/core/angular/component-fixture.js.map +1 -1
  10. package/core/angular/element.js +44 -50
  11. package/core/angular/element.js.map +1 -1
  12. package/core/angular/elements/checkbox-element.js +12 -16
  13. package/core/angular/elements/checkbox-element.js.map +1 -1
  14. package/core/angular/elements/index.js +1 -1
  15. package/core/angular/elements/radio-element.js +12 -16
  16. package/core/angular/elements/radio-element.js.map +1 -1
  17. package/core/angular/elements/select-element.js +28 -49
  18. package/core/angular/elements/select-element.js.map +1 -1
  19. package/core/angular/elements/slider-element.js +38 -42
  20. package/core/angular/elements/slider-element.js.map +1 -1
  21. package/core/angular/group.js +9 -14
  22. package/core/angular/group.js.map +1 -1
  23. package/core/angular/groups/index.js +1 -1
  24. package/core/angular/groups/radio-group.js +25 -62
  25. package/core/angular/groups/radio-group.js.map +1 -1
  26. package/core/angular/index.js +1 -1
  27. package/core/angular/page-fixture.js +8 -11
  28. package/core/angular/page-fixture.js.map +1 -1
  29. package/core/angular-materials/autocomplete-material.js +8 -11
  30. package/core/angular-materials/autocomplete-material.js.map +1 -1
  31. package/core/angular-materials/index.js +1 -1
  32. package/core/angular-materials/select-material.js +12 -15
  33. package/core/angular-materials/select-material.js.map +1 -1
  34. package/core/angular-materials/slider-material.js +5 -8
  35. package/core/angular-materials/slider-material.js.map +1 -1
  36. package/core/component-fixture.js +28 -33
  37. package/core/component-fixture.js.map +1 -1
  38. package/core/element.js +24 -26
  39. package/core/element.js.map +1 -1
  40. package/core/elements/checkbox-element.js +12 -16
  41. package/core/elements/checkbox-element.js.map +1 -1
  42. package/core/elements/index.js +1 -1
  43. package/core/elements/radio-element.js +12 -16
  44. package/core/elements/radio-element.js.map +1 -1
  45. package/core/elements/select-element.js +10 -13
  46. package/core/elements/select-element.js.map +1 -1
  47. package/core/elements/slider-element.js +5 -8
  48. package/core/elements/slider-element.js.map +1 -1
  49. package/core/group.js +9 -15
  50. package/core/group.js.map +1 -1
  51. package/core/groups/index.js +1 -1
  52. package/core/groups/radio-group.js +8 -11
  53. package/core/groups/radio-group.js.map +1 -1
  54. package/core/helpers.js +11 -16
  55. package/core/helpers.js.map +1 -1
  56. package/core/index.js +1 -1
  57. package/core/page-fixture.js +8 -11
  58. package/core/page-fixture.js.map +1 -1
  59. package/core/playwright/angular-materials/autocomplete-material.js +26 -56
  60. package/core/playwright/angular-materials/autocomplete-material.js.map +1 -1
  61. package/core/playwright/angular-materials/index.js +1 -1
  62. package/core/playwright/angular-materials/select-material.js +48 -110
  63. package/core/playwright/angular-materials/select-material.js.map +1 -1
  64. package/core/playwright/angular-materials/slider-material.js +7 -10
  65. package/core/playwright/angular-materials/slider-material.js.map +1 -1
  66. package/core/playwright/component-fixture.js +88 -173
  67. package/core/playwright/component-fixture.js.map +1 -1
  68. package/core/playwright/element.js +38 -90
  69. package/core/playwright/element.js.map +1 -1
  70. package/core/playwright/elements/checkbox-element.js +49 -94
  71. package/core/playwright/elements/checkbox-element.js.map +1 -1
  72. package/core/playwright/elements/index.js +1 -1
  73. package/core/playwright/elements/radio-element.js +18 -34
  74. package/core/playwright/elements/radio-element.js.map +1 -1
  75. package/core/playwright/elements/select-element.js +14 -21
  76. package/core/playwright/elements/select-element.js.map +1 -1
  77. package/core/playwright/elements/slider-element.js +78 -157
  78. package/core/playwright/elements/slider-element.js.map +1 -1
  79. package/core/playwright/group.js +9 -14
  80. package/core/playwright/group.js.map +1 -1
  81. package/core/playwright/groups/index.js +1 -1
  82. package/core/playwright/groups/radio-group.js +27 -64
  83. package/core/playwright/groups/radio-group.js.map +1 -1
  84. package/core/playwright/index.js +1 -1
  85. package/core/playwright/page-fixture.js +8 -18
  86. package/core/playwright/page-fixture.js.map +1 -1
  87. package/errors/fixture-usage-error.js +5 -10
  88. package/errors/fixture-usage-error.js.map +1 -1
  89. package/errors/index.js +1 -1
  90. package/errors/transpilation-purpose-only.js +5 -10
  91. package/errors/transpilation-purpose-only.js.map +1 -1
  92. package/kassette/index.js +1 -1
  93. package/kassette/update-dates-in-mocks.js +66 -85
  94. package/kassette/update-dates-in-mocks.js.map +1 -1
  95. package/localization/index.js +1 -1
  96. package/localization/localization-mock.js +38 -60
  97. package/localization/localization-mock.js.map +1 -1
  98. package/mocks/index.js +1 -1
  99. package/mocks/mock-component-generator.js +54 -53
  100. package/mocks/mock-component-generator.js.map +1 -1
  101. package/package.json +60 -59
  102. package/public_api.js +1 -1
  103. package/schematics/add-functions-to-fixture/models.d.ts.map +1 -1
  104. package/schematics/add-functions-to-fixture/models.js.map +1 -1
  105. package/schematics/ng-add/index.d.ts.map +1 -1
  106. package/schematics/ng-add/index.js +4 -6
  107. package/schematics/ng-add/index.js.map +1 -1
  108. package/schematics/ng-add/playwright/index.d.ts.map +1 -1
  109. package/schematics/ng-add/playwright/index.js +3 -4
  110. package/schematics/ng-add/playwright/index.js.map +1 -1
  111. package/schematics/ng-add/schema.json +2 -1
  112. package/schematics/playwright/sanity/schema.json +2 -1
  113. package/schematics/playwright/scenario/schema.json +2 -1
  114. package/store/index.js +1 -1
  115. package/store/testable-select.js +13 -13
  116. package/store/testable-select.js.map +1 -1
  117. package/tools/index.js +1 -1
  118. package/tools/path-replacement/index.js +1 -1
  119. package/tools/path-replacement/path-replacement.js +24 -20
  120. package/tools/path-replacement/path-replacement.js.map +1 -1
  121. package/visual-test/index.js +1 -1
  122. package/visual-test/utils.js +18 -7
  123. package/visual-test/utils.js.map +1 -1
  124. package/visual-test/visual-test.d.ts.map +1 -1
  125. package/visual-test/visual-test.js +30 -35
  126. package/visual-test/visual-test.js.map +1 -1
  127. package/visual-testing-reporter/index.d.ts.map +1 -1
  128. package/visual-testing-reporter/index.js +37 -40
  129. package/visual-testing-reporter/index.js.map +1 -1
@@ -1,98 +1,79 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.updateDatesInMocks = updateDatesInMocks;
4
- var tslib_1 = require("tslib");
5
- var temporal_polyfill_1 = require("temporal-polyfill");
4
+ const temporal_polyfill_1 = require("temporal-polyfill");
6
5
  /**
7
6
  * Update mock checksum and response body to keep using the same mocks every day with updated dates
8
7
  * @param mock the mock instance provided by the hook method of Kassette
9
8
  * @param inputOptions default options will extract ISO strings and use 'day-offset' mode
10
9
  */
11
- function updateDatesInMocks(mock_1) {
12
- return tslib_1.__awaiter(this, arguments, void 0, function (mock, inputOptions) {
13
- var plainDateLength, options, todayTime, replaceDatesInInput, checksum, _a, localPayload, referenceTime, timeOffset_1, replaceDatesInOutput, wrappedPayload;
14
- var _b, _c;
15
- if (inputOptions === void 0) { inputOptions = {}; }
16
- return tslib_1.__generator(this, function (_d) {
17
- switch (_d.label) {
18
- case 0:
19
- plainDateLength = 'YYYY-MM-DDThh:mm:ss'.length;
20
- options = tslib_1.__assign({ mode: 'day-offset', extractor: /\b(\d{4}-\d{2}-\d{2})[^"]*/g, converter: {
21
- fromDate: function (date) { return date.toString().substring(0, plainDateLength); },
22
- toDate: function (input) {
23
- input = input.replace(/\.\d+/, '').replace(/Z/, '+00:00');
24
- return input.length > plainDateLength
25
- ? temporal_polyfill_1.Temporal.ZonedDateTime.from("".concat(input.replace(/(\.\d+)/, ''), "[").concat(input.replace(/^.*(\+\d{2}:\d{2}).*$/, '$1') || '+00:00', "]"))
26
- : temporal_polyfill_1.Temporal.PlainDate.from(input);
27
- }
28
- } }, inputOptions);
29
- todayTime = temporal_polyfill_1.Temporal.Now.plainDateISO();
30
- replaceDatesInInput = function (input) {
31
- switch (options.mode) {
32
- case 'any': {
33
- return input.replace(options.extractor, '<any>');
34
- }
35
- case 'day-offset': {
36
- return input.replace(options.extractor, function (match) { return "<t+".concat(temporal_polyfill_1.Temporal.PlainDate.from(todayTime).until(options.converter.toDate(match)).toString(), ">"); });
37
- }
38
- case 'same-day-of-week': {
39
- return input.replace(options.extractor, function (match) { return "<day ".concat(options.converter.toDate(match).dayOfWeek, " next week>"); });
40
- }
10
+ async function updateDatesInMocks(mock, inputOptions = {}) {
11
+ const plainDateLength = 'YYYY-MM-DDThh:mm:ss'.length;
12
+ const options = {
13
+ mode: 'day-offset',
14
+ extractor: /\b(\d{4}-\d{2}-\d{2})[^"]*/g,
15
+ converter: {
16
+ fromDate: (date) => date.toString().substring(0, plainDateLength),
17
+ toDate: (input) => {
18
+ input = input.replace(/\.\d+/, '').replace(/Z/, '+00:00');
19
+ return input.length > plainDateLength
20
+ ? temporal_polyfill_1.Temporal.ZonedDateTime.from(`${input.replace(/(\.\d+)/, '')}[${input.replace(/^.*(\+\d{2}:\d{2}).*$/, '$1') || '+00:00'}]`)
21
+ : temporal_polyfill_1.Temporal.PlainDate.from(input);
22
+ }
23
+ },
24
+ ...inputOptions
25
+ };
26
+ const todayTime = temporal_polyfill_1.Temporal.Now.plainDateISO();
27
+ // Update request
28
+ const replaceDatesInInput = (input) => {
29
+ switch (options.mode) {
30
+ case 'any': {
31
+ return input.replace(options.extractor, '<any>');
32
+ }
33
+ case 'day-offset': {
34
+ return input.replace(options.extractor, (match) => `<t+${temporal_polyfill_1.Temporal.PlainDate.from(todayTime).until(options.converter.toDate(match)).toString()}>`);
35
+ }
36
+ case 'same-day-of-week': {
37
+ return input.replace(options.extractor, (match) => `<day ${options.converter.toDate(match).dayOfWeek} next week>`);
38
+ }
39
+ }
40
+ return input;
41
+ };
42
+ const checksum = await mock.checksum({
43
+ headers: false,
44
+ body: { filter: (body) => replaceDatesInInput(body.toString()) },
45
+ query: { filter: (params) => Object.fromEntries(Object.entries(params).map(([key, value]) => [key, replaceDatesInInput(value)])) },
46
+ customData: { updateDatesMode: options.mode }
47
+ });
48
+ mock.setLocalPath([mock.localPath, checksum]);
49
+ // Update response
50
+ if (/get|post/.test(mock.request.method) && (await mock.hasLocalMock())) {
51
+ const localPayload = (await mock.readLocalPayload())?.payload;
52
+ if (localPayload && localPayload.data.creationDateTime) {
53
+ const referenceTime = temporal_polyfill_1.Temporal.PlainDate.from(localPayload.data.creationDateTime.toISOString().substring(0, 10));
54
+ const timeOffset = temporal_polyfill_1.Temporal.PlainDate.from(referenceTime).until(todayTime, { smallestUnit: 'days', largestUnit: 'days' });
55
+ if (timeOffset.days !== 0) {
56
+ mock.setMode('manual');
57
+ const replaceDatesInOutput = (output) => {
58
+ switch (options.mode) {
59
+ case 'any':
60
+ case 'day-offset': {
61
+ return output.replace(options.extractor, (match) => options.converter.fromDate(options.converter.toDate(match).add(timeOffset)));
41
62
  }
42
- return input;
43
- };
44
- return [4 /*yield*/, mock.checksum({
45
- headers: false,
46
- body: { filter: function (body) { return replaceDatesInInput(body.toString()); } },
47
- query: { filter: function (params) { return Object.fromEntries(Object.entries(params).map(function (_a) {
48
- var key = _a[0], value = _a[1];
49
- return [key, replaceDatesInInput(value)];
50
- })); } },
51
- customData: { updateDatesMode: options.mode }
52
- })];
53
- case 1:
54
- checksum = _d.sent();
55
- mock.setLocalPath([mock.localPath, checksum]);
56
- _a = /get|post/.test(mock.request.method);
57
- if (!_a) return [3 /*break*/, 3];
58
- return [4 /*yield*/, mock.hasLocalMock()];
59
- case 2:
60
- _a = (_d.sent());
61
- _d.label = 3;
62
- case 3:
63
- if (!_a) return [3 /*break*/, 6];
64
- return [4 /*yield*/, mock.readLocalPayload()];
65
- case 4:
66
- localPayload = (_b = (_d.sent())) === null || _b === void 0 ? void 0 : _b.payload;
67
- if (!(localPayload && localPayload.data.creationDateTime)) return [3 /*break*/, 6];
68
- referenceTime = temporal_polyfill_1.Temporal.PlainDate.from(localPayload.data.creationDateTime.toISOString().substring(0, 10));
69
- timeOffset_1 = temporal_polyfill_1.Temporal.PlainDate.from(referenceTime).until(todayTime, { smallestUnit: 'days', largestUnit: 'days' });
70
- if (!(timeOffset_1.days !== 0)) return [3 /*break*/, 6];
71
- mock.setMode('manual');
72
- replaceDatesInOutput = function (output) {
73
- switch (options.mode) {
74
- case 'any':
75
- case 'day-offset': {
76
- return output.replace(options.extractor, function (match) { return options.converter.fromDate(options.converter.toDate(match).add(timeOffset_1)); });
77
- }
78
- case 'same-day-of-week': {
79
- return output.replace(options.extractor, function (match) { return options.converter.fromDate(options.converter.toDate(match).add("P".concat(Math.ceil(timeOffset_1.days / 7), "W"))); });
80
- }
63
+ case 'same-day-of-week': {
64
+ return output.replace(options.extractor, (match) => options.converter.fromDate(options.converter.toDate(match).add(`P${Math.ceil(timeOffset.days / 7)}W`)));
81
65
  }
82
- return output;
83
- };
84
- wrappedPayload = mock.createPayload({
85
- data: localPayload.data,
86
- body: replaceDatesInOutput(((_c = localPayload.body) === null || _c === void 0 ? void 0 : _c.toString()) || '')
87
- });
88
- mock.fillResponseFromPayload(wrappedPayload);
89
- return [4 /*yield*/, mock.sendResponse()];
90
- case 5:
91
- _d.sent();
92
- _d.label = 6;
93
- case 6: return [2 /*return*/];
66
+ }
67
+ return output;
68
+ };
69
+ const wrappedPayload = mock.createPayload({
70
+ data: localPayload.data,
71
+ body: replaceDatesInOutput(localPayload.body?.toString() || '')
72
+ });
73
+ mock.fillResponseFromPayload(wrappedPayload);
74
+ await mock.sendResponse();
94
75
  }
95
- });
96
- });
76
+ }
77
+ }
97
78
  }
98
79
  //# sourceMappingURL=update-dates-in-mocks.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update-dates-in-mocks.js","sourceRoot":"","sources":["../../src/kassette/update-dates-in-mocks.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n IMock,\n} from '@amadeus-it-group/kassette';\nimport {\n Temporal,\n} from 'temporal-polyfill';\n\n/**\n * Options to be passed to `updateDatesInMocks`\n */\nexport interface UpdateDatesInMocksOptions {\n /**\n * 'any': dates in inputs will be ignored when computing checksum, the dates on the output will be updated to keep the same day offset\n * 'day-offset': dates in inputs will be converted to day offsets, the dates on the output will be updated to keep the same day offset\n * 'same-day-of-week': dates in inputs will be converted to day of week, the dates on the output will be updated to keep the same day of week but increment the week\n */\n mode: 'any' | 'day-offset' | 'same-day-of-week';\n /**\n * RegExp used to extract dates from request and response\n */\n extractor: RegExp;\n /**\n * Functions to be used to convert from Temporal objects to strings, and strings to temporal objects\n */\n converter: {\n /**\n * Converter from Temporal to string\n * @param input\n */\n fromDate: (input: Temporal.ZonedDateTime | Temporal.PlainDate) => string;\n /**\n * Converter from string to Temporal\n * @param input\n */\n toDate: (input: string) => Temporal.ZonedDateTime | Temporal.PlainDate;\n };\n}\n\n/**\n * Update mock checksum and response body to keep using the same mocks every day with updated dates\n * @param mock the mock instance provided by the hook method of Kassette\n * @param inputOptions default options will extract ISO strings and use 'day-offset' mode\n */\nexport async function updateDatesInMocks(mock: IMock, inputOptions: Partial<UpdateDatesInMocksOptions> = {}) {\n const plainDateLength = 'YYYY-MM-DDThh:mm:ss'.length;\n const options = {\n mode: 'day-offset',\n extractor: /\\b(\\d{4}-\\d{2}-\\d{2})[^\"]*/g,\n converter: {\n fromDate: (date) => date.toString().substring(0, plainDateLength),\n toDate: (input) => {\n input = input.replace(/\\.\\d+/, '').replace(/Z/, '+00:00');\n return input.length > plainDateLength\n ? Temporal.ZonedDateTime.from(`${input.replace(/(\\.\\d+)/, '')}[${input.replace(/^.*(\\+\\d{2}:\\d{2}).*$/, '$1') || '+00:00'}]`)\n : Temporal.PlainDate.from(input);\n }\n },\n ...inputOptions\n } as const satisfies UpdateDatesInMocksOptions;\n const todayTime = Temporal.Now.plainDateISO();\n\n // Update request\n const replaceDatesInInput = (input: string): string => {\n switch (options.mode) {\n case 'any': {\n return input.replace(options.extractor, '<any>');\n }\n case 'day-offset': {\n return input.replace(options.extractor, (match) => `<t+${Temporal.PlainDate.from(todayTime).until(options.converter.toDate(match)).toString()}>`);\n }\n case 'same-day-of-week': {\n return input.replace(options.extractor, (match) => `<day ${options.converter.toDate(match).dayOfWeek} next week>`);\n }\n }\n return input;\n };\n const checksum = await mock.checksum({\n headers: false,\n body: { filter: (body) => replaceDatesInInput(body.toString()) },\n query: { filter: (params) => Object.fromEntries(Object.entries(params).map(([key, value]) => [key, replaceDatesInInput(value)])) },\n customData: { updateDatesMode: options.mode }\n });\n mock.setLocalPath([mock.localPath, checksum]);\n\n // Update response\n if (/get|post/.test(mock.request.method) && (await mock.hasLocalMock())) {\n const localPayload = (await mock.readLocalPayload())?.payload;\n if (localPayload && localPayload.data.creationDateTime) {\n const referenceTime = Temporal.PlainDate.from(localPayload.data.creationDateTime.toISOString().substring(0, 10));\n const timeOffset = Temporal.PlainDate.from(referenceTime).until(todayTime, { smallestUnit: 'days', largestUnit: 'days' });\n if (timeOffset.days !== 0) {\n mock.setMode('manual');\n const replaceDatesInOutput = (output: string): string => {\n switch (options.mode) {\n case 'any':\n case 'day-offset': {\n return output.replace(options.extractor, (match) => options.converter.fromDate(options.converter.toDate(match).add(timeOffset)));\n }\n case 'same-day-of-week': {\n return output.replace(options.extractor, (match) => options.converter.fromDate(options.converter.toDate(match).add(`P${Math.ceil(timeOffset.days / 7)}W`)));\n }\n }\n return output;\n };\n const wrappedPayload = mock.createPayload({\n data: localPayload.data,\n body: replaceDatesInOutput(localPayload.body?.toString() || '')\n });\n mock.fillResponseFromPayload(wrappedPayload);\n await mock.sendResponse();\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"update-dates-in-mocks.js","sourceRoot":"","sources":["../../src/kassette/update-dates-in-mocks.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n IMock,\n} from '@amadeus-it-group/kassette';\nimport {\n Temporal,\n} from 'temporal-polyfill';\n\n/**\n * Options to be passed to `updateDatesInMocks`\n */\nexport interface UpdateDatesInMocksOptions {\n /**\n * 'any': dates in inputs will be ignored when computing checksum, the dates on the output will be updated to keep the same day offset\n * 'day-offset': dates in inputs will be converted to day offsets, the dates on the output will be updated to keep the same day offset\n * 'same-day-of-week': dates in inputs will be converted to day of week, the dates on the output will be updated to keep the same day of week but increment the week\n */\n mode: 'any' | 'day-offset' | 'same-day-of-week';\n /**\n * RegExp used to extract dates from request and response\n */\n extractor: RegExp;\n /**\n * Functions to be used to convert from Temporal objects to strings, and strings to temporal objects\n */\n converter: {\n /**\n * Converter from Temporal to string\n * @param input\n */\n fromDate: (input: Temporal.ZonedDateTime | Temporal.PlainDate) => string;\n /**\n * Converter from string to Temporal\n * @param input\n */\n toDate: (input: string) => Temporal.ZonedDateTime | Temporal.PlainDate;\n };\n}\n\n/**\n * Update mock checksum and response body to keep using the same mocks every day with updated dates\n * @param mock the mock instance provided by the hook method of Kassette\n * @param inputOptions default options will extract ISO strings and use 'day-offset' mode\n */\nexport async function updateDatesInMocks(mock: IMock, inputOptions: Partial<UpdateDatesInMocksOptions> = {}) {\n const plainDateLength = 'YYYY-MM-DDThh:mm:ss'.length;\n const options = {\n mode: 'day-offset',\n extractor: /\\b(\\d{4}-\\d{2}-\\d{2})[^\"]*/g,\n converter: {\n fromDate: (date) => date.toString().substring(0, plainDateLength),\n toDate: (input) => {\n input = input.replace(/\\.\\d+/, '').replace(/Z/, '+00:00');\n return input.length > plainDateLength\n ? Temporal.ZonedDateTime.from(`${input.replace(/(\\.\\d+)/, '')}[${input.replace(/^.*(\\+\\d{2}:\\d{2}).*$/, '$1') || '+00:00'}]`)\n : Temporal.PlainDate.from(input);\n }\n },\n ...inputOptions\n } as const satisfies UpdateDatesInMocksOptions;\n const todayTime = Temporal.Now.plainDateISO();\n\n // Update request\n const replaceDatesInInput = (input: string): string => {\n switch (options.mode) {\n case 'any': {\n return input.replace(options.extractor, '<any>');\n }\n case 'day-offset': {\n return input.replace(options.extractor, (match) => `<t+${Temporal.PlainDate.from(todayTime).until(options.converter.toDate(match)).toString()}>`);\n }\n case 'same-day-of-week': {\n return input.replace(options.extractor, (match) => `<day ${options.converter.toDate(match).dayOfWeek} next week>`);\n }\n }\n return input;\n };\n const checksum = await mock.checksum({\n headers: false,\n body: { filter: (body) => replaceDatesInInput(body.toString()) },\n query: { filter: (params) => Object.fromEntries(Object.entries(params).map(([key, value]) => [key, replaceDatesInInput(value)])) },\n customData: { updateDatesMode: options.mode }\n });\n mock.setLocalPath([mock.localPath, checksum]);\n\n // Update response\n if (/get|post/.test(mock.request.method) && (await mock.hasLocalMock())) {\n const localPayload = (await mock.readLocalPayload())?.payload;\n if (localPayload && localPayload.data.creationDateTime) {\n const referenceTime = Temporal.PlainDate.from(localPayload.data.creationDateTime.toISOString().substring(0, 10));\n const timeOffset = Temporal.PlainDate.from(referenceTime).until(todayTime, { smallestUnit: 'days', largestUnit: 'days' });\n if (timeOffset.days !== 0) {\n mock.setMode('manual');\n const replaceDatesInOutput = (output: string): string => {\n switch (options.mode) {\n case 'any':\n case 'day-offset': {\n return output.replace(options.extractor, (match) => options.converter.fromDate(options.converter.toDate(match).add(timeOffset)));\n }\n case 'same-day-of-week': {\n return output.replace(options.extractor, (match) => options.converter.fromDate(options.converter.toDate(match).add(`P${Math.ceil(timeOffset.days / 7)}W`)));\n }\n }\n return output;\n };\n const wrappedPayload = mock.createPayload({\n data: localPayload.data,\n body: replaceDatesInOutput(localPayload.body?.toString() || '')\n });\n mock.fillResponseFromPayload(wrappedPayload);\n await mock.sendResponse();\n }\n }\n }\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var tslib_1 = require("tslib");
3
+ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./localization-mock"), exports);
5
5
  //# sourceMappingURL=index.js.map
@@ -1,71 +1,52 @@
1
1
  "use strict";
2
+ var LocalizationDependencyMocks_1;
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.LocalizationDependencyMocks = exports.O3rTranslatePipeMock = exports.TranslatePipeMock = void 0;
4
5
  exports.mockTranslationModules = mockTranslationModules;
5
- var tslib_1 = require("tslib");
6
- var core_1 = require("@angular/core");
7
- var core_2 = require("@ngx-translate/core");
8
- var localization_1 = require("@o3r/localization");
9
- var rxjs_1 = require("rxjs");
10
- var defaultLocalizationConfiguration = {
6
+ const tslib_1 = require("tslib");
7
+ const core_1 = require("@angular/core");
8
+ const core_2 = require("@ngx-translate/core");
9
+ const localization_1 = require("@o3r/localization");
10
+ const rxjs_1 = require("rxjs");
11
+ const defaultLocalizationConfiguration = {
11
12
  supportedLocales: ['en'],
12
13
  language: 'en',
13
14
  endPointUrl: '',
14
15
  fallbackLanguage: 'en'
15
16
  };
16
- var TranslatePipeMock = /** @class */ (function () {
17
- function TranslatePipeMock() {
17
+ let TranslatePipeMock = class TranslatePipeMock {
18
+ transform(...args) {
19
+ return args && args.map((arg) => JSON.parse(arg)).join(', ');
18
20
  }
19
- TranslatePipeMock.prototype.transform = function () {
20
- var args = [];
21
- for (var _i = 0; _i < arguments.length; _i++) {
22
- args[_i] = arguments[_i];
23
- }
24
- return args && args.map(function (arg) { return JSON.parse(arg); }).join(', ');
25
- };
26
- TranslatePipeMock = tslib_1.__decorate([
27
- (0, core_1.Pipe)({ name: 'translate' })
28
- ], TranslatePipeMock);
29
- return TranslatePipeMock;
30
- }());
21
+ };
31
22
  exports.TranslatePipeMock = TranslatePipeMock;
32
- var O3rTranslatePipeMock = /** @class */ (function () {
33
- function O3rTranslatePipeMock() {
23
+ exports.TranslatePipeMock = TranslatePipeMock = tslib_1.__decorate([
24
+ (0, core_1.Pipe)({ name: 'translate' })
25
+ ], TranslatePipeMock);
26
+ let O3rTranslatePipeMock = class O3rTranslatePipeMock {
27
+ transform(...args) {
28
+ return args && args.map((arg) => JSON.parse(arg)).join(', ');
34
29
  }
35
- O3rTranslatePipeMock.prototype.transform = function () {
36
- var args = [];
37
- for (var _i = 0; _i < arguments.length; _i++) {
38
- args[_i] = arguments[_i];
39
- }
40
- return args && args.map(function (arg) { return JSON.parse(arg); }).join(', ');
41
- };
42
- O3rTranslatePipeMock = tslib_1.__decorate([
43
- (0, core_1.Pipe)({ name: 'o3rTranslate' })
44
- ], O3rTranslatePipeMock);
45
- return O3rTranslatePipeMock;
46
- }());
30
+ };
47
31
  exports.O3rTranslatePipeMock = O3rTranslatePipeMock;
48
- var LocalizationDependencyMocks = /** @class */ (function () {
49
- function LocalizationDependencyMocks() {
50
- }
51
- LocalizationDependencyMocks_1 = LocalizationDependencyMocks;
52
- LocalizationDependencyMocks.forTest = function (pipeWithPrefix) {
53
- if (pipeWithPrefix === void 0) { pipeWithPrefix = false; }
32
+ exports.O3rTranslatePipeMock = O3rTranslatePipeMock = tslib_1.__decorate([
33
+ (0, core_1.Pipe)({ name: 'o3rTranslate' })
34
+ ], O3rTranslatePipeMock);
35
+ let LocalizationDependencyMocks = LocalizationDependencyMocks_1 = class LocalizationDependencyMocks {
36
+ static forTest(pipeWithPrefix = false) {
54
37
  return {
55
38
  ngModule: LocalizationDependencyMocks_1,
56
39
  providers: [{ provide: localization_1.O3rLocalizationTranslatePipe, useClass: pipeWithPrefix ? O3rTranslatePipeMock : TranslatePipeMock }]
57
40
  };
58
- };
59
- var LocalizationDependencyMocks_1;
60
- LocalizationDependencyMocks = LocalizationDependencyMocks_1 = tslib_1.__decorate([
61
- (0, core_1.NgModule)({
62
- declarations: [TranslatePipeMock, O3rTranslatePipeMock],
63
- exports: [TranslatePipeMock, O3rTranslatePipeMock]
64
- })
65
- ], LocalizationDependencyMocks);
66
- return LocalizationDependencyMocks;
67
- }());
41
+ }
42
+ };
68
43
  exports.LocalizationDependencyMocks = LocalizationDependencyMocks;
44
+ exports.LocalizationDependencyMocks = LocalizationDependencyMocks = LocalizationDependencyMocks_1 = tslib_1.__decorate([
45
+ (0, core_1.NgModule)({
46
+ declarations: [TranslatePipeMock, O3rTranslatePipeMock],
47
+ exports: [TranslatePipeMock, O3rTranslatePipeMock]
48
+ })
49
+ ], LocalizationDependencyMocks);
69
50
  /**
70
51
  * Function to get the list of modules required to test component using Localization module
71
52
  * @param localizationConfiguration Localization configuration
@@ -75,22 +56,19 @@ exports.LocalizationDependencyMocks = LocalizationDependencyMocks;
75
56
  * @param pipeWithPrefix Enable pipe with prefix
76
57
  * @returns List of modules to import in the TestBed
77
58
  */
78
- function mockTranslationModules(localizationConfiguration, translations, translationCompilerProvider, mockPipe, pipeWithPrefix) {
79
- if (localizationConfiguration === void 0) { localizationConfiguration = defaultLocalizationConfiguration; }
80
- if (translations === void 0) { translations = {}; }
81
- if (mockPipe === void 0) { mockPipe = false; }
82
- if (pipeWithPrefix === void 0) { pipeWithPrefix = false; }
83
- return tslib_1.__spreadArray([
84
- localization_1.LocalizationModule.forRoot(function () { return localizationConfiguration; }),
59
+ function mockTranslationModules(localizationConfiguration = defaultLocalizationConfiguration, translations = {}, translationCompilerProvider, mockPipe = false, pipeWithPrefix = false) {
60
+ return [
61
+ localization_1.LocalizationModule.forRoot(() => localizationConfiguration),
85
62
  core_2.TranslateModule.forRoot({
86
63
  loader: {
87
64
  provide: core_2.TranslateLoader,
88
65
  useValue: {
89
- getTranslation: function (lang) { return (0, rxjs_1.of)(translations[lang]); }
66
+ getTranslation: (lang) => (0, rxjs_1.of)(translations[lang])
90
67
  }
91
68
  },
92
69
  compiler: translationCompilerProvider
93
- })
94
- ], (mockPipe ? [LocalizationDependencyMocks.forTest(pipeWithPrefix)] : []), true);
70
+ }),
71
+ ...(mockPipe ? [LocalizationDependencyMocks.forTest(pipeWithPrefix)] : [])
72
+ ];
95
73
  }
96
74
  //# sourceMappingURL=localization-mock.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"localization-mock.js","sourceRoot":"","sources":["../../src/localization/localization-mock.ts"],"names":[],"mappings":";;;AAsEA,wDAoBC;;AA1FD,sCAMuB;AACvB,4CAG6B;AAC7B,kDAI2B;AAC3B,6BAEc;AAEd,IAAM,gCAAgC,GAAG;IACvC,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxB,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,EAAE;IACf,gBAAgB,EAAE,IAAI;CAC+B,CAAC;AAGxD;IAAA;IAIA,CAAC;IAHQ,qCAAS,GAAhB;QAAiB,cAAc;aAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;YAAd,yBAAc;;QAC7B,OAAO,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAf,CAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IAHU,iBAAiB;QAD7B,IAAA,WAAI,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;OACf,iBAAiB,CAI7B;IAAD,wBAAC;CAAA,AAJD,IAIC;AAJY,8CAAiB;AAO9B;IAAA;IAIA,CAAC;IAHQ,wCAAS,GAAhB;QAAiB,cAAc;aAAd,UAAc,EAAd,qBAAc,EAAd,IAAc;YAAd,yBAAc;;QAC7B,OAAO,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,UAAC,GAAG,IAAK,OAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAf,CAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;IAHU,oBAAoB;QADhC,IAAA,WAAI,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;OAClB,oBAAoB,CAIhC;IAAD,2BAAC;CAAA,AAJD,IAIC;AAJY,oDAAoB;AAUjC;IAAA;IAOA,CAAC;oCAPY,2BAA2B;IACxB,mCAAO,GAArB,UAAsB,cAAsB;QAAtB,+BAAA,EAAA,sBAAsB;QAC1C,OAAO;YACL,QAAQ,EAAE,6BAA2B;YACrC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,2CAA4B,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;SAC5H,CAAC;IACJ,CAAC;;IANU,2BAA2B;QAJvC,IAAA,eAAQ,EAAC;YACR,YAAY,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;YACvD,OAAO,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;SACnD,CAAC;OACW,2BAA2B,CAOvC;IAAD,kCAAC;CAAA,AAPD,IAOC;AAPY,kEAA2B;AAgBxC;;;;;;;;GAQG;AACH,SAAgB,sBAAsB,CACpC,yBAAgG,EAChG,YAAmC,EACnC,2BAAsC,EACtC,QAAgB,EAChB,cAAsB;IAJtB,0CAAA,EAAA,4DAAgG;IAChG,6BAAA,EAAA,iBAAmC;IAEnC,yBAAA,EAAA,gBAAgB;IAChB,+BAAA,EAAA,sBAAsB;IAEtB;QACE,iCAAkB,CAAC,OAAO,CAAC,cAAM,OAAA,yBAAyB,EAAzB,CAAyB,CAAC;QAC3D,sBAAe,CAAC,OAAO,CAAC;YACtB,MAAM,EAAE;gBACN,OAAO,EAAE,sBAAe;gBACxB,QAAQ,EAAE;oBACR,cAAc,EAAE,UAAC,IAAY,IAAK,OAAA,IAAA,SAAE,EAAC,YAAY,CAAC,IAAI,CAAC,CAAC,EAAtB,CAAsB;iBACzD;aACF;YACD,QAAQ,EAAE,2BAA2B;SACtC,CAAC;OACC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,QAC1E;AACJ,CAAC","sourcesContent":["import {\n ModuleWithProviders,\n NgModule,\n Pipe,\n PipeTransform,\n Provider,\n} from '@angular/core';\nimport {\n TranslateLoader,\n TranslateModule,\n} from '@ngx-translate/core';\nimport {\n LocalizationConfiguration,\n LocalizationModule,\n O3rLocalizationTranslatePipe,\n} from '@o3r/localization';\nimport {\n of,\n} from 'rxjs';\n\nconst defaultLocalizationConfiguration = {\n supportedLocales: ['en'],\n language: 'en',\n endPointUrl: '',\n fallbackLanguage: 'en'\n} as const satisfies Partial<LocalizationConfiguration>;\n\n@Pipe({ name: 'translate' })\nexport class TranslatePipeMock implements PipeTransform {\n public transform(...args: any[]): string | undefined {\n return args && args.map((arg) => JSON.parse(arg)).join(', ');\n }\n}\n\n@Pipe({ name: 'o3rTranslate' })\nexport class O3rTranslatePipeMock implements PipeTransform {\n public transform(...args: any[]): string | undefined {\n return args && args.map((arg) => JSON.parse(arg)).join(', ');\n }\n}\n\n@NgModule({\n declarations: [TranslatePipeMock, O3rTranslatePipeMock],\n exports: [TranslatePipeMock, O3rTranslatePipeMock]\n})\nexport class LocalizationDependencyMocks {\n public static forTest(pipeWithPrefix = false): ModuleWithProviders<LocalizationDependencyMocks> {\n return {\n ngModule: LocalizationDependencyMocks,\n providers: [{ provide: O3rLocalizationTranslatePipe, useClass: pipeWithPrefix ? O3rTranslatePipeMock : TranslatePipeMock }]\n };\n }\n}\n\n/** Mock to provide to the MockTranslation module */\nexport interface MockTranslations {\n [lang: string]: {\n [key: string]: any;\n };\n}\n\n/**\n * Function to get the list of modules required to test component using Localization module\n * @param localizationConfiguration Localization configuration\n * @param translations Translations to use\n * @param translationCompilerProvider Provider for translations compiler\n * @param mockPipe Enable translation pipe mocking\n * @param pipeWithPrefix Enable pipe with prefix\n * @returns List of modules to import in the TestBed\n */\nexport function mockTranslationModules(\n localizationConfiguration: Partial<LocalizationConfiguration> = defaultLocalizationConfiguration,\n translations: MockTranslations = {},\n translationCompilerProvider?: Provider,\n mockPipe = false,\n pipeWithPrefix = false\n): ModuleWithProviders<LocalizationModule>[] {\n return [\n LocalizationModule.forRoot(() => localizationConfiguration),\n TranslateModule.forRoot({\n loader: {\n provide: TranslateLoader,\n useValue: {\n getTranslation: (lang: string) => of(translations[lang])\n }\n },\n compiler: translationCompilerProvider\n }),\n ...(mockPipe ? [LocalizationDependencyMocks.forTest(pipeWithPrefix)] : [])\n ];\n}\n"]}
1
+ {"version":3,"file":"localization-mock.js","sourceRoot":"","sources":["../../src/localization/localization-mock.ts"],"names":[],"mappings":";;;;AAsEA,wDAoBC;;AA1FD,wCAMuB;AACvB,8CAG6B;AAC7B,oDAI2B;AAC3B,+BAEc;AAEd,MAAM,gCAAgC,GAAG;IACvC,gBAAgB,EAAE,CAAC,IAAI,CAAC;IACxB,QAAQ,EAAE,IAAI;IACd,WAAW,EAAE,EAAE;IACf,gBAAgB,EAAE,IAAI;CAC+B,CAAC;AAGjD,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IACrB,SAAS,CAAC,GAAG,IAAW;QAC7B,OAAO,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;CACF,CAAA;AAJY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,WAAI,EAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;GACf,iBAAiB,CAI7B;AAGM,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IACxB,SAAS,CAAC,GAAG,IAAW;QAC7B,OAAO,IAAI,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/D,CAAC;CACF,CAAA;AAJY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,WAAI,EAAC,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;GAClB,oBAAoB,CAIhC;AAMM,IAAM,2BAA2B,mCAAjC,MAAM,2BAA2B;IAC/B,MAAM,CAAC,OAAO,CAAC,cAAc,GAAG,KAAK;QAC1C,OAAO;YACL,QAAQ,EAAE,6BAA2B;YACrC,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,2CAA4B,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC;SAC5H,CAAC;IACJ,CAAC;CACF,CAAA;AAPY,kEAA2B;sCAA3B,2BAA2B;IAJvC,IAAA,eAAQ,EAAC;QACR,YAAY,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;QACvD,OAAO,EAAE,CAAC,iBAAiB,EAAE,oBAAoB,CAAC;KACnD,CAAC;GACW,2BAA2B,CAOvC;AASD;;;;;;;;GAQG;AACH,SAAgB,sBAAsB,CACpC,4BAAgE,gCAAgC,EAChG,eAAiC,EAAE,EACnC,2BAAsC,EACtC,QAAQ,GAAG,KAAK,EAChB,cAAc,GAAG,KAAK;IAEtB,OAAO;QACL,iCAAkB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,yBAAyB,CAAC;QAC3D,sBAAe,CAAC,OAAO,CAAC;YACtB,MAAM,EAAE;gBACN,OAAO,EAAE,sBAAe;gBACxB,QAAQ,EAAE;oBACR,cAAc,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,IAAA,SAAE,EAAC,YAAY,CAAC,IAAI,CAAC,CAAC;iBACzD;aACF;YACD,QAAQ,EAAE,2BAA2B;SACtC,CAAC;QACF,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3E,CAAC;AACJ,CAAC","sourcesContent":["import {\n ModuleWithProviders,\n NgModule,\n Pipe,\n PipeTransform,\n Provider,\n} from '@angular/core';\nimport {\n TranslateLoader,\n TranslateModule,\n} from '@ngx-translate/core';\nimport {\n LocalizationConfiguration,\n LocalizationModule,\n O3rLocalizationTranslatePipe,\n} from '@o3r/localization';\nimport {\n of,\n} from 'rxjs';\n\nconst defaultLocalizationConfiguration = {\n supportedLocales: ['en'],\n language: 'en',\n endPointUrl: '',\n fallbackLanguage: 'en'\n} as const satisfies Partial<LocalizationConfiguration>;\n\n@Pipe({ name: 'translate' })\nexport class TranslatePipeMock implements PipeTransform {\n public transform(...args: any[]): string | undefined {\n return args && args.map((arg) => JSON.parse(arg)).join(', ');\n }\n}\n\n@Pipe({ name: 'o3rTranslate' })\nexport class O3rTranslatePipeMock implements PipeTransform {\n public transform(...args: any[]): string | undefined {\n return args && args.map((arg) => JSON.parse(arg)).join(', ');\n }\n}\n\n@NgModule({\n declarations: [TranslatePipeMock, O3rTranslatePipeMock],\n exports: [TranslatePipeMock, O3rTranslatePipeMock]\n})\nexport class LocalizationDependencyMocks {\n public static forTest(pipeWithPrefix = false): ModuleWithProviders<LocalizationDependencyMocks> {\n return {\n ngModule: LocalizationDependencyMocks,\n providers: [{ provide: O3rLocalizationTranslatePipe, useClass: pipeWithPrefix ? O3rTranslatePipeMock : TranslatePipeMock }]\n };\n }\n}\n\n/** Mock to provide to the MockTranslation module */\nexport interface MockTranslations {\n [lang: string]: {\n [key: string]: any;\n };\n}\n\n/**\n * Function to get the list of modules required to test component using Localization module\n * @param localizationConfiguration Localization configuration\n * @param translations Translations to use\n * @param translationCompilerProvider Provider for translations compiler\n * @param mockPipe Enable translation pipe mocking\n * @param pipeWithPrefix Enable pipe with prefix\n * @returns List of modules to import in the TestBed\n */\nexport function mockTranslationModules(\n localizationConfiguration: Partial<LocalizationConfiguration> = defaultLocalizationConfiguration,\n translations: MockTranslations = {},\n translationCompilerProvider?: Provider,\n mockPipe = false,\n pipeWithPrefix = false\n): ModuleWithProviders<LocalizationModule>[] {\n return [\n LocalizationModule.forRoot(() => localizationConfiguration),\n TranslateModule.forRoot({\n loader: {\n provide: TranslateLoader,\n useValue: {\n getTranslation: (lang: string) => of(translations[lang])\n }\n },\n compiler: translationCompilerProvider\n }),\n ...(mockPipe ? [LocalizationDependencyMocks.forTest(pipeWithPrefix)] : [])\n ];\n}\n"]}
package/mocks/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- var tslib_1 = require("tslib");
3
+ const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./mock-component-generator"), exports);
5
5
  //# sourceMappingURL=index.js.map
@@ -1,10 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.generateMockComponent = generateMockComponent;
4
- var tslib_1 = require("tslib");
5
- var core_1 = require("@angular/core");
6
- var forms_1 = require("@angular/forms");
7
- var ts = require("typescript");
4
+ const core_1 = require("@angular/core");
5
+ const forms_1 = require("@angular/forms");
6
+ const ts = require("typescript");
8
7
  /**
9
8
  * Determine if the node in an input field
10
9
  * @param node Typescript AST Node
@@ -28,18 +27,18 @@ function isOutputNode(node, source) {
28
27
  * @param source Typescript source file
29
28
  */
30
29
  function getIOName(currentNode, decorator, source) {
31
- var nameInDecorator = decorator.getText(source).match(/@(input|output) *\( *(["'](.*)["'])? *\) */i);
30
+ const nameInDecorator = decorator.getText(source).match(/@(input|output) *\( *(["'](.*)["'])? *\) */i);
32
31
  if (nameInDecorator && nameInDecorator[3]) {
33
32
  return nameInDecorator[3];
34
33
  }
35
34
  else {
36
- var name_1;
37
- currentNode.forEachChild(function (node) {
35
+ let name;
36
+ currentNode.forEachChild((node) => {
38
37
  if (ts.isIdentifier(node)) {
39
- name_1 = node.getText(source);
38
+ name = node.getText(source);
40
39
  }
41
40
  });
42
- return name_1;
41
+ return name;
43
42
  }
44
43
  }
45
44
  /**
@@ -48,30 +47,30 @@ function getIOName(currentNode, decorator, source) {
48
47
  * @param source Typescript source file
49
48
  */
50
49
  function parseIO(parentNode, source) {
51
- var outputs = [];
52
- var inputs = [];
53
- parentNode.forEachChild(function (node) {
50
+ const outputs = [];
51
+ const inputs = [];
52
+ parentNode.forEachChild((node) => {
54
53
  if (isInputNode(node, source)) {
55
- var name_2 = getIOName(parentNode, node, source);
56
- if (name_2) {
57
- inputs.push(name_2);
54
+ const name = getIOName(parentNode, node, source);
55
+ if (name) {
56
+ inputs.push(name);
58
57
  }
59
58
  }
60
59
  else if (isOutputNode(node, source)) {
61
- var name_3 = getIOName(parentNode, node, source);
62
- if (name_3) {
63
- outputs.push(name_3);
60
+ const name = getIOName(parentNode, node, source);
61
+ if (name) {
62
+ outputs.push(name);
64
63
  }
65
64
  }
66
65
  else {
67
- var childrenResult = parseIO(node, source);
68
- inputs.push.apply(inputs, childrenResult.inputs);
69
- outputs.push.apply(outputs, childrenResult.outputs);
66
+ const childrenResult = parseIO(node, source);
67
+ inputs.push(...childrenResult.inputs);
68
+ outputs.push(...childrenResult.outputs);
70
69
  }
71
70
  });
72
71
  return {
73
- outputs: outputs,
74
- inputs: inputs
72
+ outputs,
73
+ inputs
75
74
  };
76
75
  }
77
76
  /**
@@ -81,13 +80,11 @@ function parseIO(parentNode, source) {
81
80
  * @param isInDecorator true if the recursive execution is in a decorator
82
81
  * @param isInComponentConfig true if the recursive execution is in a component decorator configuration
83
82
  */
84
- function getSelector(parentNode, source, isInDecorator, isInComponentConfig) {
85
- if (isInDecorator === void 0) { isInDecorator = false; }
86
- if (isInComponentConfig === void 0) { isInComponentConfig = false; }
87
- var foundDecorator = false;
88
- var foundSelector = false;
89
- var ret;
90
- parentNode.forEachChild(function (node) {
83
+ function getSelector(parentNode, source, isInDecorator = false, isInComponentConfig = false) {
84
+ let foundDecorator = false;
85
+ let foundSelector = false;
86
+ let ret;
87
+ parentNode.forEachChild((node) => {
91
88
  if (isInDecorator && isInComponentConfig && ts.isIdentifier(node) && node.getText(source) === 'selector') {
92
89
  foundSelector = true;
93
90
  }
@@ -128,35 +125,39 @@ function getSelector(parentNode, source, isInDecorator, isInComponentConfig) {
128
125
  * ```
129
126
  */
130
127
  function generateMockComponent(componentPath, config) {
131
- var program = ts.createProgram([componentPath], {});
132
- var source = program.getSourceFile(componentPath);
128
+ const program = ts.createProgram([componentPath], {});
129
+ const source = program.getSourceFile(componentPath);
133
130
  if (!source) {
134
131
  throw new Error('No Source found');
135
132
  }
136
- var _a = parseIO(source, source), outputs = _a.outputs, inputs = _a.inputs;
137
- var mock = /** @class */ (function () {
138
- function class_1() {
139
- var _this = this;
133
+ const { outputs, inputs } = parseIO(source, source);
134
+ const mock = class {
135
+ constructor() {
140
136
  Object.keys(outputs)
141
- .forEach(function (outputName) { return _this[outputName] = new core_1.EventEmitter(); });
137
+ .forEach((outputName) => this[outputName] = new core_1.EventEmitter());
142
138
  if (config && config.isControlValueAccessor) {
143
- this.writeValue = function () { };
144
- this.registerOnChange = function () { };
145
- this.registerOnTouched = function () { };
139
+ this.writeValue = () => { };
140
+ this.registerOnChange = () => { };
141
+ this.registerOnTouched = () => { };
146
142
  }
147
143
  }
148
- return class_1;
149
- }());
150
- return (0, core_1.Component)(tslib_1.__assign({ template: (config === null || config === void 0 ? void 0 : config.template) || '', selector: getSelector(source, source) || '', inputs: inputs, outputs: outputs }, (config && config.isControlValueAccessor)
151
- ? {
152
- providers: [
153
- {
154
- provide: forms_1.NG_VALUE_ACCESSOR,
155
- useExisting: (0, core_1.forwardRef)(function () { return mock; }),
156
- multi: true
157
- }
158
- ]
159
- }
160
- : {}))(mock);
144
+ };
145
+ return (0, core_1.Component)({
146
+ template: config?.template || '',
147
+ selector: getSelector(source, source) || '',
148
+ inputs,
149
+ outputs,
150
+ ...(config && config.isControlValueAccessor)
151
+ ? {
152
+ providers: [
153
+ {
154
+ provide: forms_1.NG_VALUE_ACCESSOR,
155
+ useExisting: (0, core_1.forwardRef)(() => mock),
156
+ multi: true
157
+ }
158
+ ]
159
+ }
160
+ : {}
161
+ })(mock);
161
162
  }
162
163
  //# sourceMappingURL=mock-component-generator.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"mock-component-generator.js","sourceRoot":"","sources":["../../src/mocks/mock-component-generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n EventEmitter,\n forwardRef,\n Type,\n} from '@angular/core';\nimport {\n NG_VALUE_ACCESSOR,\n} from '@angular/forms';\nimport * as ts from 'typescript';\n\n/**\n * Determine if the node in an input field\n * @param node Typescript AST Node\n * @param source Typescript source file\n */\nfunction isInputNode(node: ts.Node, source: ts.SourceFile): node is ts.Decorator {\n return ts.isDecorator(node) && node.getText(source).startsWith('@Input');\n}\n\n/**\n * Determine if the node in an output field\n * @param node Typescript AST Node\n * @param source Typescript source file\n */\nfunction isOutputNode(node: ts.Node, source: ts.SourceFile): node is ts.Decorator {\n return ts.isDecorator(node) && node.getText(source).startsWith('@Output');\n}\n\n/**\n * Get the name of the input / output\n * @param currentNode Typescript AST Node\n * @param decorator Current Input/Output decorator node\n * @param source Typescript source file\n */\nfunction getIOName(currentNode: ts.Node, decorator: ts.Decorator, source: ts.SourceFile): string | undefined {\n const nameInDecorator = decorator.getText(source).match(/@(input|output) *\\( *([\"'](.*)[\"'])? *\\) */i);\n if (nameInDecorator && nameInDecorator[3]) {\n return nameInDecorator[3];\n } else {\n let name: string | undefined;\n currentNode.forEachChild((node) => {\n if (ts.isIdentifier(node)) {\n name = node.getText(source);\n }\n });\n return name;\n }\n}\n\n/**\n * Get the list of Input and Output of a component\n * @param parentNode Typescript AST Node\n * @param source Typescript source file\n */\nfunction parseIO(parentNode: ts.Node, source: ts.SourceFile): { outputs: string[]; inputs: string[] } {\n const outputs: string[] = [];\n const inputs: string[] = [];\n\n parentNode.forEachChild((node) => {\n if (isInputNode(node, source)) {\n const name = getIOName(parentNode, node, source);\n if (name) {\n inputs.push(name);\n }\n } else if (isOutputNode(node, source)) {\n const name = getIOName(parentNode, node, source);\n if (name) {\n outputs.push(name);\n }\n } else {\n const childrenResult = parseIO(node, source);\n inputs.push(...childrenResult.inputs);\n outputs.push(...childrenResult.outputs);\n }\n });\n\n return {\n outputs,\n inputs\n };\n}\n\n/**\n * Get the selector of an angular class\n * @param parentNode Typescript AST Node\n * @param source Typescript source file\n * @param isInDecorator true if the recursive execution is in a decorator\n * @param isInComponentConfig true if the recursive execution is in a component decorator configuration\n */\nfunction getSelector(parentNode: ts.Node, source: ts.SourceFile, isInDecorator = false, isInComponentConfig = false) {\n let foundDecorator = false;\n let foundSelector = false;\n let ret: string | undefined;\n parentNode.forEachChild((node) => {\n if (isInDecorator && isInComponentConfig && ts.isIdentifier(node) && node.getText(source) === 'selector') {\n foundSelector = true;\n } else if (foundSelector && ts.isStringLiteral(node)) {\n ret = node.getText(source).replace(/[\"']/gi, '');\n } else if (isInDecorator && ts.isIdentifier(node) && node.getText(source) === 'Component') {\n foundDecorator = true;\n } else if (isInDecorator && foundDecorator && ts.isObjectLiteralExpression(node)) {\n ret = ret || getSelector(node, source, isInDecorator, true);\n } else {\n ret = ret || getSelector(node, source, isInDecorator || ts.isDecorator(node), isInComponentConfig);\n }\n });\n return ret;\n}\n\n/**\n * Generate a mock class base on a component file\n * @param componentPath Path to the component file to mock\n * @param config Object containing the following configurations:\n * template: should be provided if the template contain `<ng-content></ng-content>`\n * isControlValueAccessor: should be provided if the component extends ControlValueAccessor\n * @param config.template\n * @param config.isControlValueAccessor\n * @example\n * ```typescript\n * // hero.component.ts\n * \\@Component({selector: 'hero'})\n * class HeroComponent {\n * \\@Input() name: string;\n * \\@Output() doSomething: EventEmitter<void>\n * }\n *\n * // mock generation\n * class MockComponent extends generateMockComponent('hero.component.ts') {}\n * ```\n */\nexport function generateMockComponent<T = Record<string, unknown>>(componentPath: string, config?: { template?: string; isControlValueAccessor?: boolean }): Type<T> {\n const program = ts.createProgram([componentPath], {});\n const source = program.getSourceFile(componentPath);\n if (!source) {\n throw new Error('No Source found');\n }\n\n const { outputs, inputs } = parseIO(source, source);\n const mock = class {\n public writeValue: any;\n public registerOnChange: any;\n public registerOnTouched: any;\n\n constructor() {\n Object.keys(outputs)\n .forEach((outputName) => (this as any)[outputName] = new EventEmitter<any>());\n if (config && config.isControlValueAccessor) {\n this.writeValue = () => {};\n this.registerOnChange = () => {};\n this.registerOnTouched = () => {};\n }\n }\n };\n\n return Component({\n template: config?.template || '',\n selector: getSelector(source, source) || '',\n inputs,\n outputs,\n ...(config && config.isControlValueAccessor)\n ? {\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => mock),\n multi: true\n }\n ]\n }\n : {}\n })(mock) as Type<T>;\n}\n"]}
1
+ {"version":3,"file":"mock-component-generator.js","sourceRoot":"","sources":["../../src/mocks/mock-component-generator.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Component,\n EventEmitter,\n forwardRef,\n Type,\n} from '@angular/core';\nimport {\n NG_VALUE_ACCESSOR,\n} from '@angular/forms';\nimport * as ts from 'typescript';\n\n/**\n * Determine if the node in an input field\n * @param node Typescript AST Node\n * @param source Typescript source file\n */\nfunction isInputNode(node: ts.Node, source: ts.SourceFile): node is ts.Decorator {\n return ts.isDecorator(node) && node.getText(source).startsWith('@Input');\n}\n\n/**\n * Determine if the node in an output field\n * @param node Typescript AST Node\n * @param source Typescript source file\n */\nfunction isOutputNode(node: ts.Node, source: ts.SourceFile): node is ts.Decorator {\n return ts.isDecorator(node) && node.getText(source).startsWith('@Output');\n}\n\n/**\n * Get the name of the input / output\n * @param currentNode Typescript AST Node\n * @param decorator Current Input/Output decorator node\n * @param source Typescript source file\n */\nfunction getIOName(currentNode: ts.Node, decorator: ts.Decorator, source: ts.SourceFile): string | undefined {\n const nameInDecorator = decorator.getText(source).match(/@(input|output) *\\( *([\"'](.*)[\"'])? *\\) */i);\n if (nameInDecorator && nameInDecorator[3]) {\n return nameInDecorator[3];\n } else {\n let name: string | undefined;\n currentNode.forEachChild((node) => {\n if (ts.isIdentifier(node)) {\n name = node.getText(source);\n }\n });\n return name;\n }\n}\n\n/**\n * Get the list of Input and Output of a component\n * @param parentNode Typescript AST Node\n * @param source Typescript source file\n */\nfunction parseIO(parentNode: ts.Node, source: ts.SourceFile): { outputs: string[]; inputs: string[] } {\n const outputs: string[] = [];\n const inputs: string[] = [];\n\n parentNode.forEachChild((node) => {\n if (isInputNode(node, source)) {\n const name = getIOName(parentNode, node, source);\n if (name) {\n inputs.push(name);\n }\n } else if (isOutputNode(node, source)) {\n const name = getIOName(parentNode, node, source);\n if (name) {\n outputs.push(name);\n }\n } else {\n const childrenResult = parseIO(node, source);\n inputs.push(...childrenResult.inputs);\n outputs.push(...childrenResult.outputs);\n }\n });\n\n return {\n outputs,\n inputs\n };\n}\n\n/**\n * Get the selector of an angular class\n * @param parentNode Typescript AST Node\n * @param source Typescript source file\n * @param isInDecorator true if the recursive execution is in a decorator\n * @param isInComponentConfig true if the recursive execution is in a component decorator configuration\n */\nfunction getSelector(parentNode: ts.Node, source: ts.SourceFile, isInDecorator = false, isInComponentConfig = false) {\n let foundDecorator = false;\n let foundSelector = false;\n let ret: string | undefined;\n parentNode.forEachChild((node) => {\n if (isInDecorator && isInComponentConfig && ts.isIdentifier(node) && node.getText(source) === 'selector') {\n foundSelector = true;\n } else if (foundSelector && ts.isStringLiteral(node)) {\n ret = node.getText(source).replace(/[\"']/gi, '');\n } else if (isInDecorator && ts.isIdentifier(node) && node.getText(source) === 'Component') {\n foundDecorator = true;\n } else if (isInDecorator && foundDecorator && ts.isObjectLiteralExpression(node)) {\n ret = ret || getSelector(node, source, isInDecorator, true);\n } else {\n ret = ret || getSelector(node, source, isInDecorator || ts.isDecorator(node), isInComponentConfig);\n }\n });\n return ret;\n}\n\n/**\n * Generate a mock class base on a component file\n * @param componentPath Path to the component file to mock\n * @param config Object containing the following configurations:\n * template: should be provided if the template contain `<ng-content></ng-content>`\n * isControlValueAccessor: should be provided if the component extends ControlValueAccessor\n * @param config.template\n * @param config.isControlValueAccessor\n * @example\n * ```typescript\n * // hero.component.ts\n * \\@Component({selector: 'hero'})\n * class HeroComponent {\n * \\@Input() name: string;\n * \\@Output() doSomething: EventEmitter<void>\n * }\n *\n * // mock generation\n * class MockComponent extends generateMockComponent('hero.component.ts') {}\n * ```\n */\nexport function generateMockComponent<T = Record<string, unknown>>(componentPath: string, config?: { template?: string; isControlValueAccessor?: boolean }): Type<T> {\n const program = ts.createProgram([componentPath], {});\n const source = program.getSourceFile(componentPath);\n if (!source) {\n throw new Error('No Source found');\n }\n\n const { outputs, inputs } = parseIO(source, source);\n const mock = class {\n public writeValue: any;\n public registerOnChange: any;\n public registerOnTouched: any;\n\n constructor() {\n Object.keys(outputs)\n .forEach((outputName) => (this as any)[outputName] = new EventEmitter<any>());\n if (config && config.isControlValueAccessor) {\n this.writeValue = () => {};\n this.registerOnChange = () => {};\n this.registerOnTouched = () => {};\n }\n }\n };\n\n return Component({\n template: config?.template || '',\n selector: getSelector(source, source) || '',\n inputs,\n outputs,\n ...(config && config.isControlValueAccessor)\n ? {\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n useExisting: forwardRef(() => mock),\n multi: true\n }\n ]\n }\n : {}\n })(mock) as Type<T>;\n}\n"]}