@shopgate/pwa-core 7.30.0-alpha.7 → 7.30.0-alpha.9

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 (85) hide show
  1. package/classes/AppCommand/index.js +115 -11
  2. package/classes/AppCommand/spec.js +260 -6
  3. package/classes/AppCommandRequest/index.js +129 -20
  4. package/classes/AppPermissionsRequest/AppPermissionsRequest.js +45 -7
  5. package/classes/AppPermissionsRequest/GetAppPermissionsRequest.js +48 -9
  6. package/classes/AppPermissionsRequest/RequestAppPermissionsRequest.js +54 -9
  7. package/classes/Bridge/index.js +34 -4
  8. package/classes/Bridge/spec.js +24 -1
  9. package/classes/BrightnessRequest/index.js +59 -10
  10. package/classes/BrightnessRequest/spec.js +111 -6
  11. package/classes/BrowserConnector/index.js +180 -26
  12. package/classes/Conditioner/index.js +74 -8
  13. package/classes/Conditioner/spec.js +75 -1
  14. package/classes/DataRequest/index.js +116 -13
  15. package/classes/DevServerBridge/index.js +85 -9
  16. package/classes/DevServerBridge/spec.js +230 -14
  17. package/classes/ErrorManager/index.js +144 -20
  18. package/classes/ErrorManager/spec.js +244 -2
  19. package/classes/Event/index.js +101 -15
  20. package/classes/HttpRequest/index.js +182 -21
  21. package/classes/PipelineDependencies/index.js +42 -6
  22. package/classes/PipelineDependencies/spec.js +46 -3
  23. package/classes/PipelineManager/index.js +517 -71
  24. package/classes/PipelineManager/spec.js +733 -15
  25. package/classes/PipelineRequest/index.js +167 -19
  26. package/classes/PipelineRequest/mock.js +118 -21
  27. package/classes/PipelineRequest/spec.js +333 -2
  28. package/classes/PipelineSequence/index.js +34 -6
  29. package/classes/Request/index.js +61 -13
  30. package/classes/RequestBuffer/index.js +43 -6
  31. package/classes/RequestManager/index.js +216 -33
  32. package/classes/RequestManager/spec.js +188 -1
  33. package/classes/Scanner/index.js +246 -67
  34. package/classes/ScannerEvent/index.js +23 -9
  35. package/classes/ScannerEventHandler/index.js +39 -16
  36. package/classes/ScannerEventListener/index.js +84 -24
  37. package/classes/ScannerManager/ScanProcessingError.js +11 -3
  38. package/classes/ScannerManager/index.js +133 -21
  39. package/classes/WebStorageRequest/index.js +76 -9
  40. package/commands/analyticsSetCustomValues.js +8 -2
  41. package/commands/appPermissions.js +10 -3
  42. package/commands/brightness.js +33 -5
  43. package/commands/broadcastEvent.js +8 -2
  44. package/commands/cleanTab.js +11 -3
  45. package/commands/closeInAppBrowser.js +22 -2
  46. package/commands/flushTab.js +8 -2
  47. package/commands/getWebStorageEntry.js +11 -2
  48. package/commands/hideMenuBar.js +8 -2
  49. package/commands/hideNavigationBar.js +8 -2
  50. package/commands/hideSplashScreen.js +8 -2
  51. package/commands/onload.js +13 -3
  52. package/commands/openAppSettings.js +8 -2
  53. package/commands/openPage.js +8 -2
  54. package/commands/openPageExtern.js +8 -2
  55. package/commands/performCommandsAfterDelay.js +11 -3
  56. package/commands/plotProjects.js +65 -7
  57. package/commands/popTabToRoot.js +11 -3
  58. package/commands/registerEvents.js +10 -2
  59. package/commands/scanner.js +76 -7
  60. package/commands/setCookie.js +8 -2
  61. package/commands/setDebugLoggingEnabled.js +8 -2
  62. package/commands/setScrollingEnabled.js +7 -2
  63. package/commands/setWebStorageEntry.js +8 -2
  64. package/commands/shareItem.js +18 -2
  65. package/commands/showNavigationBar.js +8 -2
  66. package/commands/showTab.js +13 -2
  67. package/commands/unifiedTracking.js +128 -30
  68. package/constants/AppCommands.js +6 -1
  69. package/constants/AppEvents.js +9 -1
  70. package/constants/AppPermissions.js +57 -13
  71. package/constants/Command.js +1 -1
  72. package/constants/ErrorHandleTypes.js +2 -1
  73. package/constants/ErrorManager.js +15 -1
  74. package/constants/Pipeline.js +52 -17
  75. package/constants/ProcessTypes.js +3 -1
  76. package/constants/RequestManagerModes.js +19 -7
  77. package/constants/RequestTypes.js +2 -1
  78. package/constants/Scanner.js +39 -10
  79. package/constants/Trilean.js +6 -1
  80. package/emitters/ui.js +2 -1
  81. package/helpers/index.js +66 -8
  82. package/helpers/logGroup.js +56 -8
  83. package/helpers/version.js +216 -22
  84. package/index.js +60 -5
  85. package/package.json +1 -2
@@ -1,29 +1,105 @@
1
- function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}import fetch from'isomorphic-fetch';import{logger}from"../../helpers";import event from"../Event";/**
1
+ import { logger } from "../../helpers";
2
+ import event from "../Event";
3
+
4
+ /**
2
5
  * The DevServerBridge emulates the SGJavaScriptBridge within browser environments.
3
6
  * It routes supported app commands to the Frontend SDK which can mimic the behavior of the app.
4
- */var DevServerBridge=/*#__PURE__*/function(){/**
7
+ */
8
+ class DevServerBridge {
9
+ /**
5
10
  * The constructor.
6
11
  * @param {string} ip The IP of the dev server.
7
12
  * @param {number} port The port of the dev server.
8
- */function DevServerBridge(){var ip=arguments.length>0&&arguments[0]!==undefined?arguments[0]:process.env.IP;var port=arguments.length>1&&arguments[1]!==undefined?arguments[1]:process.env.PORT;_classCallCheck(this,DevServerBridge);this.ip=ip;this.port=port;this.supportedCommands=['sendPipelineRequest','sendHttpRequest','sendDataRequest','getWebStorageEntry'];}/**
13
+ */
14
+ constructor(ip = process.env.IP, port = process.env.PORT) {
15
+ this.ip = ip;
16
+ this.port = port;
17
+ this.supportedCommands = ['sendPipelineRequest', 'sendHttpRequest', 'sendDataRequest', 'getWebStorageEntry'];
18
+ }
19
+
20
+ /**
9
21
  * Dispatches multiple commands to the dev server.
10
22
  * @param {Array} commands The commands to dispatch.
11
23
  * @param {string} libVersion The lib version for the command.
12
24
  * @return {DevServerBridge}
13
- */return _createClass(DevServerBridge,[{key:"dispatchCommandsForVersion",value:function dispatchCommandsForVersion(commands,libVersion){var _this=this;if(Array.isArray(commands)){commands.forEach(function(command){_this.dispatchCommandForVersion(command,libVersion);});}return this;}/**
25
+ */
26
+ dispatchCommandsForVersion(commands, libVersion) {
27
+ if (Array.isArray(commands)) {
28
+ commands.forEach(command => {
29
+ this.dispatchCommandForVersion(command, libVersion);
30
+ });
31
+ }
32
+ return this;
33
+ }
34
+
35
+ /**
14
36
  * Dispatches a single command to the dev server.
15
37
  * @param {Object} command The command to dispatch.
16
38
  * @param {string} libVersion The lib version for the command.
17
39
  * @return {DevServerBridge}
18
- */},{key:"dispatchCommandForVersion",value:function dispatchCommandForVersion(command,libVersion){var _ref=command||{},name=_ref.c;if(this.supportedCommands.includes(name)){// Append an optional suffix for special command related endpoints
19
- var suffix='';if(name==='getWebStorageEntry'){suffix='web_storage';}else if(name==='sendHttpRequest'){suffix='http_request';}var url="http://".concat(this.ip,":").concat(this.port,"/").concat(suffix);var options={method:'post',headers:new Headers({'Content-Type':'application/json'}),body:JSON.stringify({cmds:[command],ver:libVersion})};fetch(url,options).then(function(response){return response.json();}).then(this.processDevServerResponse)["catch"](function(err){return err&&logger.error(err);});}return this;}/**
40
+ */
41
+ dispatchCommandForVersion(command, libVersion) {
42
+ const {
43
+ c: name
44
+ } = command || {};
45
+ if (this.supportedCommands.includes(name)) {
46
+ // Append an optional suffix for special command related endpoints
47
+ let suffix = '';
48
+ if (name === 'getWebStorageEntry') {
49
+ suffix = 'web_storage';
50
+ } else if (name === 'sendHttpRequest') {
51
+ suffix = 'http_request';
52
+ }
53
+ const url = `http://${this.ip}:${this.port}/${suffix}`;
54
+ const options = {
55
+ method: 'post',
56
+ headers: new Headers({
57
+ 'Content-Type': 'application/json'
58
+ }),
59
+ body: JSON.stringify({
60
+ cmds: [command],
61
+ ver: libVersion
62
+ })
63
+ };
64
+ fetch(url, options).then(response => response.json()).then(this.processDevServerResponse).catch(err => err && logger.error(err));
65
+ }
66
+ return this;
67
+ }
68
+
69
+ /**
20
70
  * Handles a response of the dev server.
21
71
  * @param {Object} response The server response.
22
72
  * @return {DevServerBridge}
23
- */},{key:"processDevServerResponse",value:function processDevServerResponse(response){var _ref2=response||{},_ref2$cmds=_ref2.cmds,cmds=_ref2$cmds===void 0?[]:_ref2$cmds;// Process the response commands.
24
- cmds.forEach(function(command){var name=command.c;var params=command.p;var args=[];/**
73
+ */
74
+ processDevServerResponse(response) {
75
+ const {
76
+ cmds = []
77
+ } = response || {};
78
+
79
+ // Process the response commands.
80
+ cmds.forEach(command => {
81
+ const name = command.c;
82
+ const params = command.p;
83
+ let args = [];
84
+
85
+ /**
25
86
  * The server returns a response command for a request command.
26
87
  * If the native app receives such a command, it calls a related event within the
27
88
  * webviews. Here the response parameters are sorted in the specified order for
28
89
  * the different response events.
29
- */if(name==='pipelineResponse'){args=[params.error,params.serial,params.output];}else if(name==='httpResponse'){args=[params.error,params.serial,params.response];}else if(name==='dataResponse'){args=[params.serial,params.status,params.body,params.bodyContentType];}else if(name==='webStorageResponse'){args=[params.serial,params.age,params.value];}event.call(name,args);});return this;}}]);}();export default DevServerBridge;
90
+ */
91
+ if (name === 'pipelineResponse') {
92
+ args = [params.error, params.serial, params.output];
93
+ } else if (name === 'httpResponse') {
94
+ args = [params.error, params.serial, params.response];
95
+ } else if (name === 'dataResponse') {
96
+ args = [params.serial, params.status, params.body, params.bodyContentType];
97
+ } else if (name === 'webStorageResponse') {
98
+ args = [params.serial, params.age, params.value];
99
+ }
100
+ event.call(name, args);
101
+ });
102
+ return this;
103
+ }
104
+ }
105
+ export default DevServerBridge;
@@ -1,15 +1,231 @@
1
- function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}import DevServerBridge from"./index";// A libVersion for the bridge method calls
2
- var libVersion='16.1';var devServerIp='192.168.0.1';var devServerPort='1337';// Mocks of the env variables.
3
- global.process.env={IP:devServerIp,PORT:devServerPort};// Mocks of the global Headers class.
4
- global.Headers=function(){};// Create a mock for the fetch method.
5
- var mockedFetchResponse={};var mockedFetch;jest.mock('isomorphic-fetch',function(){return function(){return mockedFetch.apply(void 0,arguments);};});// Create a mock for the Event class.
6
- var mockedEventCall=jest.fn();jest.mock("../Event",function(){return{call:function call(){return mockedEventCall.apply(void 0,arguments);}};});// Create a mock for the error logger.
7
- var mockedLoggerError=jest.fn();jest.mock("../../helpers",function(){return{logger:{error:function error(){mockedLoggerError.apply(void 0,arguments);}}};});var dispatchCommandSpy;var processResponseSpy;/**
1
+ import DevServerBridge from "./index";
2
+
3
+ // A libVersion for the bridge method calls
4
+ const libVersion = '16.1';
5
+ const devServerIp = '192.168.0.1';
6
+ const devServerPort = '1337';
7
+
8
+ // Mocks of the env variables.
9
+ global.process.env = {
10
+ IP: devServerIp,
11
+ PORT: devServerPort
12
+ };
13
+
14
+ // Mocks of the global Headers class.
15
+ global.Headers = class Headers {};
16
+
17
+ // Create a mock for the fetch method.
18
+ const mockedFetchResponse = {};
19
+ let mockedFetch;
20
+ beforeAll(() => {
21
+ global.fetch = jest.fn(); // mock fetch globally
22
+ });
23
+
24
+ // Create a mock for the Event class.
25
+ const mockedEventCall = jest.fn();
26
+ jest.mock("../Event", () => ({
27
+ call: (...args) => mockedEventCall(...args)
28
+ }));
29
+
30
+ // Create a mock for the error logger.
31
+ const mockedLoggerError = jest.fn();
32
+ jest.mock("../../helpers", () => ({
33
+ logger: {
34
+ error: (...args) => {
35
+ mockedLoggerError(...args);
36
+ }
37
+ }
38
+ }));
39
+ let dispatchCommandSpy;
40
+ let processResponseSpy;
41
+
42
+ /**
8
43
  * Updates the mock for the fetch module.
9
- * @param {boolean} throwError Wheater the mocked fetch shall throw an error.
10
- */var updateMockedFetch=function updateMockedFetch(){var throwError=arguments.length>0&&arguments[0]!==undefined?arguments[0]:false;if(!throwError){mockedFetch=jest.fn().mockResolvedValue({json:function json(){return mockedFetchResponse;}});}else{mockedFetch=jest.fn().mockRejectedValue(new Error());}};describe('DevServerBridge',function(){var instance;beforeEach(function(){mockedEventCall.mockClear();updateMockedFetch();instance=new DevServerBridge();dispatchCommandSpy=jest.spyOn(instance,'dispatchCommandForVersion');processResponseSpy=jest.spyOn(instance,'processDevServerResponse');});describe('.constructor()',function(){it('should work as expected without parameters',function(){expect(instance.ip).toBe(devServerIp);expect(instance.port).toBe(devServerPort);});it('should apply custom parameters',function(){var customIp='127.0.0.1';var customPort='4711';instance=new DevServerBridge(customIp,customPort);expect(instance.ip).toBe(customIp);expect(instance.port).toBe(customPort);});});describe('.dispatchCommandsForVersion()',function(){it('should call dispatchCommand for every single command',function(){var commands=[{c:'sendPipelineRequest'},{c:'openPage'}];var result=instance.dispatchCommandsForVersion(commands,libVersion);expect(result).toEqual(instance);expect(dispatchCommandSpy).toHaveBeenCalledTimes(2);expect(dispatchCommandSpy.mock.calls[0][0].c).toBe('sendPipelineRequest');expect(dispatchCommandSpy.mock.calls[0][1]).toBe(libVersion);expect(dispatchCommandSpy.mock.calls[1][0].c).toBe('openPage');expect(dispatchCommandSpy.mock.calls[1][1]).toBe(libVersion);});it('should call dispatchCommand when no commands where passed',function(){var result=instance.dispatchCommandsForVersion(null,libVersion);expect(result).toEqual(instance);expect(dispatchCommandSpy).toHaveBeenCalledTimes(0);});});describe('.dispatchCommandForVersion()',function(){it('should dispatch a webStorage entry command',function(done){var name='getWebStorageEntry';var command={c:name};var result=instance.dispatchCommandForVersion(command,libVersion);expect(result).toEqual(instance);// The dispatch method has async behavior. So we wait for the next tick before we check.
11
- setTimeout(function(){expect(mockedFetch).toHaveBeenCalledTimes(1);expect(mockedFetch.mock.calls[0][0].endsWith('web_storage')).toBe(true);expect(mockedFetch.mock.calls[0][1].body.includes(name)).toBe(true);expect(processResponseSpy).toHaveBeenCalledTimes(1);done();},0);});it('should dispatch a httpRequest command',function(done){var name='sendHttpRequest';var command={c:name};var result=instance.dispatchCommandForVersion(command,libVersion);expect(result).toEqual(instance);// The dispatch method has async behavior. So we wait for the next tick before we check.
12
- setTimeout(function(){expect(mockedFetch).toHaveBeenCalledTimes(1);expect(mockedFetch.mock.calls[0][0].endsWith('http_request')).toBe(true);expect(mockedFetch.mock.calls[0][1].body.includes(name)).toBe(true);expect(processResponseSpy).toHaveBeenCalledTimes(1);done();},0);});it('should not do anything if the command is not whitelisted',function(done){var command={c:'openPage'};var result=instance.dispatchCommandForVersion(command,libVersion);expect(result).toEqual(instance);// The dispatch method has async behavior. So we wait for the next tick before we check.
13
- setTimeout(function(){expect(mockedFetch).toHaveBeenCalledTimes(0);expect(processResponseSpy).toHaveBeenCalledTimes(0);done();},0);});it('should not do anything if the command is empty',function(done){var result=instance.dispatchCommandForVersion(null,libVersion);expect(result).toEqual(instance);// The dispatch method has async behavior. So we wait for the next tick before we check.
14
- setTimeout(function(){expect(mockedFetch).toHaveBeenCalledTimes(0);expect(processResponseSpy).toHaveBeenCalledTimes(0);done();},0);});it('should handle fetch errors',function(done){updateMockedFetch(true);var command={c:'sendPipelineRequest'};var result=instance.dispatchCommandForVersion(command,libVersion);expect(result).toEqual(instance);// The dispatch method has async behavior. So we wait for the next tick before we check.
15
- setTimeout(function(){expect(mockedFetch).toHaveBeenCalledTimes(1);expect(processResponseSpy).toHaveBeenCalledTimes(0);expect(mockedLoggerError).toHaveBeenCalledTimes(1);expect(mockedLoggerError.mock.calls[0][0]).toBeInstanceOf(Error);done();},0);});});describe('.processDevServerResponse()',function(){it('should handle a response commands as expected',function(){var serial='abc123';var commands=[{c:'pipelineResponse',p:{serial:serial,error:null,output:{}}},{c:'httpResponse',p:{serial:serial,error:null,response:{}}},{c:'dataResponse',p:{serial:serial,status:200,body:'',bodyContentType:''}},{c:'webStorageResponse',p:{serial:serial,age:40,value:{}}},{c:'unknownResponse',p:{}}];var result=instance.processDevServerResponse({cmds:commands});expect(result).toEqual(instance);expect(mockedEventCall).toHaveBeenCalledTimes(5);var _mockedEventCall$mock=_slicedToArray(mockedEventCall.mock.calls,5),pipelineResponse=_mockedEventCall$mock[0],httpResponse=_mockedEventCall$mock[1],dataResponse=_mockedEventCall$mock[2],webStorageResponse=_mockedEventCall$mock[3],unknownResponse=_mockedEventCall$mock[4];expect(pipelineResponse[0]).toBe('pipelineResponse');expect(pipelineResponse[1]).toHaveLength(3);expect(pipelineResponse[1][1]).toBe(serial);expect(httpResponse[0]).toBe('httpResponse');expect(httpResponse[1]).toHaveLength(3);expect(httpResponse[1][1]).toBe(serial);expect(dataResponse[0]).toBe('dataResponse');expect(dataResponse[1]).toHaveLength(4);expect(dataResponse[1][0]).toBe(serial);expect(webStorageResponse[0]).toBe('webStorageResponse');expect(webStorageResponse[1]).toHaveLength(3);expect(webStorageResponse[1][0]).toBe(serial);expect(unknownResponse[0]).toBe('unknownResponse');expect(unknownResponse[1]).toHaveLength(0);});it('should work as expected when nothing was passed',function(){var result=instance.processDevServerResponse(null);expect(result).toEqual(instance);expect(mockedEventCall).toHaveBeenCalledTimes(0);});});});
44
+ * @param {boolean} throwError Whether the mocked fetch shall throw an error.
45
+ */
46
+ const updateMockedFetch = (throwError = false) => {
47
+ mockedFetch = throwError ? jest.fn().mockRejectedValue(new Error()) : jest.fn().mockResolvedValue({
48
+ json: () => mockedFetchResponse
49
+ });
50
+ global.fetch.mockImplementation((...args) => mockedFetch(...args));
51
+ };
52
+ describe('DevServerBridge', () => {
53
+ let instance;
54
+ beforeEach(() => {
55
+ mockedEventCall.mockClear();
56
+ updateMockedFetch();
57
+ instance = new DevServerBridge();
58
+ dispatchCommandSpy = jest.spyOn(instance, 'dispatchCommandForVersion');
59
+ processResponseSpy = jest.spyOn(instance, 'processDevServerResponse');
60
+ });
61
+ describe('.constructor()', () => {
62
+ it('should work as expected without parameters', () => {
63
+ expect(instance.ip).toBe(devServerIp);
64
+ expect(instance.port).toBe(devServerPort);
65
+ });
66
+ it('should apply custom parameters', () => {
67
+ const customIp = '127.0.0.1';
68
+ const customPort = '4711';
69
+ instance = new DevServerBridge(customIp, customPort);
70
+ expect(instance.ip).toBe(customIp);
71
+ expect(instance.port).toBe(customPort);
72
+ });
73
+ });
74
+ describe('.dispatchCommandsForVersion()', () => {
75
+ it('should call dispatchCommand for every single command', () => {
76
+ const commands = [{
77
+ c: 'sendPipelineRequest'
78
+ }, {
79
+ c: 'openPage'
80
+ }];
81
+ const result = instance.dispatchCommandsForVersion(commands, libVersion);
82
+ expect(result).toEqual(instance);
83
+ expect(dispatchCommandSpy).toHaveBeenCalledTimes(2);
84
+ expect(dispatchCommandSpy.mock.calls[0][0].c).toBe('sendPipelineRequest');
85
+ expect(dispatchCommandSpy.mock.calls[0][1]).toBe(libVersion);
86
+ expect(dispatchCommandSpy.mock.calls[1][0].c).toBe('openPage');
87
+ expect(dispatchCommandSpy.mock.calls[1][1]).toBe(libVersion);
88
+ });
89
+ it('should call dispatchCommand when no commands where passed', () => {
90
+ const result = instance.dispatchCommandsForVersion(null, libVersion);
91
+ expect(result).toEqual(instance);
92
+ expect(dispatchCommandSpy).toHaveBeenCalledTimes(0);
93
+ });
94
+ });
95
+ describe('.dispatchCommandForVersion()', () => {
96
+ it('should dispatch a webStorage entry command', done => {
97
+ const name = 'getWebStorageEntry';
98
+ const command = {
99
+ c: name
100
+ };
101
+ const result = instance.dispatchCommandForVersion(command, libVersion);
102
+ expect(result).toEqual(instance);
103
+ // The dispatch method has async behavior. So we wait for the next tick before we check.
104
+ setTimeout(() => {
105
+ expect(mockedFetch).toHaveBeenCalledTimes(1);
106
+ expect(mockedFetch.mock.calls[0][0].endsWith('web_storage')).toBe(true);
107
+ expect(mockedFetch.mock.calls[0][1].body.includes(name)).toBe(true);
108
+ expect(processResponseSpy).toHaveBeenCalledTimes(1);
109
+ done();
110
+ }, 0);
111
+ });
112
+ it('should dispatch a httpRequest command', done => {
113
+ const name = 'sendHttpRequest';
114
+ const command = {
115
+ c: name
116
+ };
117
+ const result = instance.dispatchCommandForVersion(command, libVersion);
118
+ expect(result).toEqual(instance);
119
+ // The dispatch method has async behavior. So we wait for the next tick before we check.
120
+ setTimeout(() => {
121
+ expect(mockedFetch).toHaveBeenCalledTimes(1);
122
+ expect(mockedFetch.mock.calls[0][0].endsWith('http_request')).toBe(true);
123
+ expect(mockedFetch.mock.calls[0][1].body.includes(name)).toBe(true);
124
+ expect(processResponseSpy).toHaveBeenCalledTimes(1);
125
+ done();
126
+ }, 0);
127
+ });
128
+ it('should not do anything if the command is not whitelisted', done => {
129
+ const command = {
130
+ c: 'openPage'
131
+ };
132
+ const result = instance.dispatchCommandForVersion(command, libVersion);
133
+ expect(result).toEqual(instance);
134
+ // The dispatch method has async behavior. So we wait for the next tick before we check.
135
+ setTimeout(() => {
136
+ expect(mockedFetch).toHaveBeenCalledTimes(0);
137
+ expect(processResponseSpy).toHaveBeenCalledTimes(0);
138
+ done();
139
+ }, 0);
140
+ });
141
+ it('should not do anything if the command is empty', done => {
142
+ const result = instance.dispatchCommandForVersion(null, libVersion);
143
+ expect(result).toEqual(instance);
144
+ // The dispatch method has async behavior. So we wait for the next tick before we check.
145
+ setTimeout(() => {
146
+ expect(mockedFetch).toHaveBeenCalledTimes(0);
147
+ expect(processResponseSpy).toHaveBeenCalledTimes(0);
148
+ done();
149
+ }, 0);
150
+ });
151
+ it('should handle fetch errors', done => {
152
+ updateMockedFetch(true);
153
+ const command = {
154
+ c: 'sendPipelineRequest'
155
+ };
156
+ const result = instance.dispatchCommandForVersion(command, libVersion);
157
+ expect(result).toEqual(instance);
158
+ // The dispatch method has async behavior. So we wait for the next tick before we check.
159
+ setTimeout(() => {
160
+ expect(mockedFetch).toHaveBeenCalledTimes(1);
161
+ expect(processResponseSpy).toHaveBeenCalledTimes(0);
162
+ expect(mockedLoggerError).toHaveBeenCalledTimes(1);
163
+ expect(mockedLoggerError.mock.calls[0][0]).toBeInstanceOf(Error);
164
+ done();
165
+ }, 0);
166
+ });
167
+ });
168
+ describe('.processDevServerResponse()', () => {
169
+ it('should handle a response commands as expected', () => {
170
+ const serial = 'abc123';
171
+ const commands = [{
172
+ c: 'pipelineResponse',
173
+ p: {
174
+ serial,
175
+ error: null,
176
+ output: {}
177
+ }
178
+ }, {
179
+ c: 'httpResponse',
180
+ p: {
181
+ serial,
182
+ error: null,
183
+ response: {}
184
+ }
185
+ }, {
186
+ c: 'dataResponse',
187
+ p: {
188
+ serial,
189
+ status: 200,
190
+ body: '',
191
+ bodyContentType: ''
192
+ }
193
+ }, {
194
+ c: 'webStorageResponse',
195
+ p: {
196
+ serial,
197
+ age: 40,
198
+ value: {}
199
+ }
200
+ }, {
201
+ c: 'unknownResponse',
202
+ p: {}
203
+ }];
204
+ const result = instance.processDevServerResponse({
205
+ cmds: commands
206
+ });
207
+ expect(result).toEqual(instance);
208
+ expect(mockedEventCall).toHaveBeenCalledTimes(5);
209
+ const [pipelineResponse, httpResponse, dataResponse, webStorageResponse, unknownResponse] = mockedEventCall.mock.calls;
210
+ expect(pipelineResponse[0]).toBe('pipelineResponse');
211
+ expect(pipelineResponse[1]).toHaveLength(3);
212
+ expect(pipelineResponse[1][1]).toBe(serial);
213
+ expect(httpResponse[0]).toBe('httpResponse');
214
+ expect(httpResponse[1]).toHaveLength(3);
215
+ expect(httpResponse[1][1]).toBe(serial);
216
+ expect(dataResponse[0]).toBe('dataResponse');
217
+ expect(dataResponse[1]).toHaveLength(4);
218
+ expect(dataResponse[1][0]).toBe(serial);
219
+ expect(webStorageResponse[0]).toBe('webStorageResponse');
220
+ expect(webStorageResponse[1]).toHaveLength(3);
221
+ expect(webStorageResponse[1][0]).toBe(serial);
222
+ expect(unknownResponse[0]).toBe('unknownResponse');
223
+ expect(unknownResponse[1]).toHaveLength(0);
224
+ });
225
+ it('should work as expected when nothing was passed', () => {
226
+ const result = instance.processDevServerResponse(null);
227
+ expect(result).toEqual(instance);
228
+ expect(mockedEventCall).toHaveBeenCalledTimes(0);
229
+ });
230
+ });
231
+ });
@@ -1,26 +1,100 @@
1
- import _regeneratorRuntime from"@babel/runtime/regenerator";function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function asyncGeneratorStep(gen,resolve,reject,_next,_throw,key,arg){try{var info=gen[key](arg);var value=info.value;}catch(error){reject(error);return;}if(info.done){resolve(value);}else{Promise.resolve(value).then(_next,_throw);}}function _asyncToGenerator(fn){return function(){var self=this,args=arguments;return new Promise(function(resolve,reject){var gen=fn.apply(self,args);function _next(value){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"next",value);}function _throw(err){asyncGeneratorStep(gen,resolve,reject,_next,_throw,"throw",err);}_next(undefined);});};}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}import EventEmitter from'events';import{DEFAULT_CONTEXT,SOURCE_PIPELINE,DEFAULT_SEVERITY}from"../../constants/ErrorManager";export var emitter=new EventEmitter();var pipelineVersionSuffix=/\.v\d+$/;/**
1
+ import "core-js/modules/es.string.replace.js";
2
+ import EventEmitter from 'events';
3
+ import { DEFAULT_CONTEXT, SOURCE_PIPELINE, DEFAULT_SEVERITY } from "../../constants/ErrorManager";
4
+ export const emitter = new EventEmitter();
5
+ const pipelineVersionSuffix = /\.v\d+$/;
6
+
7
+ /**
2
8
  * The ErrorManager class.
3
- */var ErrorManager=/*#__PURE__*/function(){/**
9
+ */
10
+ class ErrorManager {
11
+ /**
4
12
  * Constructor.
5
- */function ErrorManager(){var _this=this;_classCallCheck(this,ErrorManager);/**
6
- * Calls dispatch() as an interval.
7
- */_defineProperty(this,"startTimer",/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee(){return _regeneratorRuntime.wrap(function _callee$(_context){while(1)switch(_context.prev=_context.next){case 0:_context.next=2;return _this.stopTimer();case 2:_this.timer=setInterval(_this.dispatch,500);case 3:case"end":return _context.stop();}},_callee);})));/**
8
- * Clears the dispatch interval.
9
- */_defineProperty(this,"stopTimer",/*#__PURE__*/_asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee2(){return _regeneratorRuntime.wrap(function _callee2$(_context2){while(1)switch(_context2.prev=_context2.next){case 0:_context2.next=2;return clearInterval(_this.timer);case 2:_this.timer=null;case 3:case"end":return _context2.stop();}},_callee2);})));/**
10
- * Dispatched the stored error objects through the event emitter.
11
- * @returns {boolean}
12
- */_defineProperty(this,"dispatch",function(){if(_this.errorQueue.size===0){return false;}_this.errorQueue.forEach(function(error){emitter.emit(error.source,error);});_this.stopTimer();_this.errorQueue.clear();return true;});/**
13
- * Validates an error object.
14
- * @param {*} error The error object.
15
- * @returns {boolean}
16
- */_defineProperty(this,"validate",function(){var error=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var _error$code=error.code,code=_error$code===void 0?null:_error$code,_error$message=error.message,message=_error$message===void 0?null:_error$message,_error$source=error.source,source=_error$source===void 0?null:_error$source;if(!code||!message||!source){return false;}if(typeof code!=='string'||typeof source!=='string'){return false;}return typeof message==='string'||typeof message==='function';});// Queue of errors that will be dispatched.
17
- this.errorQueue=new Map();// List of override message for specific errors.
18
- this.messages={};// A variable to handle the intervals.
19
- this.timer=null;}/**
13
+ */
14
+ constructor() {
15
+ /**
16
+ * Calls dispatch() as an interval.
17
+ */
18
+ this.startTimer = async () => {
19
+ await this.stopTimer();
20
+ this.timer = setInterval(this.dispatch, 500);
21
+ };
22
+ /**
23
+ * Clears the dispatch interval.
24
+ */
25
+ this.stopTimer = async () => {
26
+ await clearInterval(this.timer);
27
+ this.timer = null;
28
+ };
29
+ /**
30
+ * Dispatched the stored error objects through the event emitter.
31
+ * @returns {boolean}
32
+ */
33
+ this.dispatch = () => {
34
+ if (this.errorQueue.size === 0) {
35
+ return false;
36
+ }
37
+ this.errorQueue.forEach(error => {
38
+ emitter.emit(error.source, error);
39
+ });
40
+ this.stopTimer();
41
+ this.errorQueue.clear();
42
+ return true;
43
+ };
44
+ /**
45
+ * Validates an error object.
46
+ * @param {*} error The error object.
47
+ * @returns {boolean}
48
+ */
49
+ this.validate = (error = {}) => {
50
+ const {
51
+ code = null,
52
+ message = null,
53
+ source = null
54
+ } = error;
55
+ if (!code || !message || !source) {
56
+ return false;
57
+ }
58
+ if (typeof code !== 'string' || typeof source !== 'string') {
59
+ return false;
60
+ }
61
+ return typeof message === 'string' || typeof message === 'function';
62
+ };
63
+ // Queue of errors that will be dispatched.
64
+ this.errorQueue = new Map();
65
+
66
+ // List of override message for specific errors.
67
+ this.messages = {};
68
+
69
+ // A variable to handle the intervals.
70
+ this.timer = null;
71
+ }
72
+
73
+ /**
20
74
  * Gets a message by the given error.
21
75
  * @param {{ code: string, context: string, source: string }} error The error object.
22
76
  * @returns {string|null}
23
- */return _createClass(ErrorManager,[{key:"getMessage",value:function getMessage(error){if(!this.validate(error)){return null;}var code=error.code,_error$context=error.context,context=_error$context===void 0?DEFAULT_CONTEXT:_error$context,source=error.source;var id="".concat(source,"-").concat(context,"-").concat(code);var unvId="".concat(source,"-").concat(context.replace(pipelineVersionSuffix,''),"-").concat(code);var defaultId="".concat(source,"-").concat(DEFAULT_CONTEXT,"-").concat(code);var message=this.messages[id]||this.messages[unvId]||this.messages[defaultId]||null;if(typeof message==='function'){message=message(error);}return message;}/**
77
+ */
78
+ getMessage(error) {
79
+ if (!this.validate(error)) {
80
+ return null;
81
+ }
82
+ const {
83
+ code,
84
+ context = DEFAULT_CONTEXT,
85
+ source
86
+ } = error;
87
+ const id = `${source}-${context}-${code}`;
88
+ const unvId = `${source}-${context.replace(pipelineVersionSuffix, '')}-${code}`;
89
+ const defaultId = `${source}-${DEFAULT_CONTEXT}-${code}`;
90
+ let message = this.messages[id] || this.messages[unvId] || this.messages[defaultId] || null;
91
+ if (typeof message === 'function') {
92
+ message = message(error);
93
+ }
94
+ return message;
95
+ }
96
+
97
+ /**
24
98
  * Sets an override for a specific error message.
25
99
  * @param {Object} errorTemplate The error object.
26
100
  * @param {string} errorTemplate.code The error code.
@@ -28,7 +102,24 @@ this.timer=null;}/**
28
102
  * @param {string} errorTemplate.message The default error message.
29
103
  * @param {string} [errorTemplate.source=SOURCE_PIPELINE] The source of the error.
30
104
  * @returns {ErrorManager}
31
- */},{key:"setMessage",value:function setMessage(){var errorTemplate=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var error=_extends({source:SOURCE_PIPELINE},errorTemplate);if(!this.validate(error)){return this;}var _error$context2=error.context,context=_error$context2===void 0?DEFAULT_CONTEXT:_error$context2;var id="".concat(error.source,"-").concat(context,"-").concat(error.code);this.messages[id]=error.message;return this;}/**
105
+ */
106
+ setMessage(errorTemplate = {}) {
107
+ const error = {
108
+ source: SOURCE_PIPELINE,
109
+ ...errorTemplate
110
+ };
111
+ if (!this.validate(error)) {
112
+ return this;
113
+ }
114
+ const {
115
+ context = DEFAULT_CONTEXT
116
+ } = error;
117
+ const id = `${error.source}-${context}-${error.code}`;
118
+ this.messages[id] = error.message;
119
+ return this;
120
+ }
121
+
122
+ /**
32
123
  * Adds a new error object to the queue.
33
124
  * @param {Object} error The error object.
34
125
  * @param {string} error.code The error code.
@@ -36,4 +127,37 @@ this.timer=null;}/**
36
127
  * @param {string} error.message The default error message.
37
128
  * @param {string} error.source The source of the error.
38
129
  * @param {Object} error.meta Some meta data.
39
- */},{key:"queue",value:function queue(){var error=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};if(!this.validate(error)){return;}var code=error.code,_error$context3=error.context,context=_error$context3===void 0?DEFAULT_CONTEXT:_error$context3,message=error.message,source=error.source,meta=error.meta,_error$severity=error.severity,severity=_error$severity===void 0?DEFAULT_SEVERITY:_error$severity;var id="".concat(source,"-").concat(context,"-").concat(code);var overrideMessage=this.getMessage(error)||message;this.errorQueue.set(id,{id:id,code:code,context:context,message:overrideMessage,meta:_extends({},meta,{message:message}),source:source,severity:severity});if(!this.timer){this.startTimer();}}}]);}();/** @type {ErrorManager} */export default new ErrorManager();
130
+ */
131
+ queue(error = {}) {
132
+ if (!this.validate(error)) {
133
+ return;
134
+ }
135
+ const {
136
+ code,
137
+ context = DEFAULT_CONTEXT,
138
+ message,
139
+ source,
140
+ meta,
141
+ severity = DEFAULT_SEVERITY
142
+ } = error;
143
+ const id = `${source}-${context}-${code}`;
144
+ const overrideMessage = this.getMessage(error) || message;
145
+ this.errorQueue.set(id, {
146
+ id,
147
+ code,
148
+ context,
149
+ message: overrideMessage,
150
+ meta: {
151
+ ...meta,
152
+ message
153
+ },
154
+ source,
155
+ severity
156
+ });
157
+ if (!this.timer) {
158
+ this.startTimer();
159
+ }
160
+ }
161
+ }
162
+ /** @type {ErrorManager} */
163
+ export default new ErrorManager();