stoobly-agent 1.4.2__py3-none-any.whl → 1.5.1__py3-none-any.whl

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 (72) hide show
  1. stoobly_agent/__init__.py +1 -1
  2. stoobly_agent/app/cli/helpers/handle_config_update_service.py +2 -2
  3. stoobly_agent/app/cli/helpers/handle_mock_service.py +6 -2
  4. stoobly_agent/app/cli/helpers/request_facade.py +5 -1
  5. stoobly_agent/app/cli/scaffold/constants.py +1 -1
  6. stoobly_agent/app/cli/scaffold/docker/workflow/mock_decorator.py +1 -0
  7. stoobly_agent/app/cli/scaffold/service_workflow_validate_command.py +19 -19
  8. stoobly_agent/app/cli/scaffold/templates/app/.Dockerfile.context +1 -1
  9. stoobly_agent/app/cli/scaffold/templates/constants.py +3 -3
  10. stoobly_agent/app/cli/scaffold/templates/factory.py +5 -5
  11. stoobly_agent/app/cli/scaffold/templates/workflow/mock/bin/configure +1 -8
  12. stoobly_agent/app/cli/scaffold/templates/workflow/mock/fixtures.yml +1 -1
  13. stoobly_agent/app/cli/scaffold/templates/workflow/test/bin/configure +1 -8
  14. stoobly_agent/app/cli/scaffold/templates/workflow/test/fixtures.yml +1 -1
  15. stoobly_agent/app/cli/scaffold/workflow_command.py +3 -3
  16. stoobly_agent/app/cli/scaffold/workflow_create_command.py +2 -2
  17. stoobly_agent/app/cli/scaffold_cli.py +5 -5
  18. stoobly_agent/app/models/factories/resource/local_db/helpers/tiebreak_scenario_request.py +1 -1
  19. stoobly_agent/app/models/factories/resource/local_db/request_adapter.py +17 -11
  20. stoobly_agent/app/models/types/request.py +1 -2
  21. stoobly_agent/app/proxy/context.py +4 -0
  22. stoobly_agent/app/proxy/handle_mock_service.py +93 -46
  23. stoobly_agent/app/proxy/handle_record_service.py +15 -3
  24. stoobly_agent/app/proxy/handle_replay_service.py +44 -18
  25. stoobly_agent/app/proxy/handle_test_service.py +92 -24
  26. stoobly_agent/app/proxy/intercept_handler.py +11 -16
  27. stoobly_agent/app/proxy/intercept_settings.py +17 -4
  28. stoobly_agent/app/proxy/mitmproxy/request_facade.py +5 -2
  29. stoobly_agent/app/proxy/mitmproxy/response_facade.py +5 -4
  30. stoobly_agent/app/proxy/mock/custom_not_found_response_builder.py +5 -0
  31. stoobly_agent/app/proxy/mock/eval_fixtures_service.py +79 -14
  32. stoobly_agent/app/proxy/mock/eval_request_service.py +18 -13
  33. stoobly_agent/app/proxy/record/join_request_service.py +7 -8
  34. stoobly_agent/app/proxy/record/upload_request_service.py +2 -2
  35. stoobly_agent/app/proxy/replay/replay_request_service.py +4 -4
  36. stoobly_agent/app/proxy/test/helpers/upload_test_service.py +2 -2
  37. stoobly_agent/app/proxy/utils/allowed_request_service.py +3 -3
  38. stoobly_agent/app/proxy/utils/response_handler.py +10 -1
  39. stoobly_agent/app/proxy/utils/rewrite.py +72 -0
  40. stoobly_agent/app/settings/constants/request_component.py +4 -1
  41. stoobly_agent/cli.py +35 -28
  42. stoobly_agent/config/constants/custom_headers.py +1 -0
  43. stoobly_agent/config/constants/intercept_policy.py +2 -0
  44. stoobly_agent/config/constants/mock_policy.py +4 -2
  45. stoobly_agent/config/constants/query_params.py +2 -0
  46. stoobly_agent/config/constants/record_policy.py +4 -2
  47. stoobly_agent/config/constants/replay_policy.py +4 -2
  48. stoobly_agent/public/{18-es2015.583f191cc7ad512ee262.js → 18-es2015.503207073756a9c8211a.js} +1 -1
  49. stoobly_agent/public/{18-es5.583f191cc7ad512ee262.js → 18-es5.503207073756a9c8211a.js} +1 -1
  50. stoobly_agent/public/index.html +1 -1
  51. stoobly_agent/public/{main-es2015.2cc16523aa3fcaba51e5.js → main-es2015.d682619f3d6d53d64c6a.js} +1 -1
  52. stoobly_agent/public/{main-es5.2cc16523aa3fcaba51e5.js → main-es5.d682619f3d6d53d64c6a.js} +1 -1
  53. stoobly_agent/public/{runtime-es2015.b914470164e4d6e75d96.js → runtime-es2015.8c1efed946fc02c923fc.js} +1 -1
  54. stoobly_agent/public/{runtime-es5.b914470164e4d6e75d96.js → runtime-es5.8c1efed946fc02c923fc.js} +1 -1
  55. stoobly_agent/test/app/cli/helpers/openapi_endpoint_adapter_test.py +2 -1
  56. stoobly_agent/test/app/cli/scaffold/e2e_test.py +2 -2
  57. stoobly_agent/test/app/models/factories/resource/local_db/helpers/tiebreak_scenario_request_test.py +4 -4
  58. stoobly_agent/test/app/models/schemas/.stoobly/db/VERSION +1 -1
  59. stoobly_agent/test/app/proxy/mock/eval_fixtures_service_test.py +140 -71
  60. stoobly_agent/test/cli/lifecycle_hooks_test.py +66 -0
  61. stoobly_agent/test/cli/mock_scenario_lifecycle_hooks.py +5 -0
  62. stoobly_agent/test/cli/mock_scenario_test.py +62 -0
  63. stoobly_agent/test/cli/mock_test.py +54 -38
  64. stoobly_agent/test/cli/record_test.py +67 -0
  65. stoobly_agent/test/mock_data/lifecycle_hooks.py +35 -0
  66. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.1.dist-info}/LICENSE +1 -1
  67. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.1.dist-info}/METADATA +7 -12
  68. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.1.dist-info}/RECORD +72 -65
  69. /stoobly_agent/app/cli/scaffold/templates/workflow/mock/{fixtures/.keep → public/.gitignore} +0 -0
  70. /stoobly_agent/app/cli/scaffold/templates/workflow/test/{fixtures/.keep → public/.gitignore} +0 -0
  71. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.1.dist-info}/WHEEL +0 -0
  72. {stoobly_agent-1.4.2.dist-info → stoobly_agent-1.5.1.dist-info}/entry_points.txt +0 -0
@@ -1 +1 @@
1
- !function(e){function r(r){for(var a,f,o=r[0],b=r[1],d=r[2],i=0,l=[];i<o.length;i++)f=o[i],Object.prototype.hasOwnProperty.call(c,f)&&c[f]&&l.push(c[f][0]),c[f]=0;for(a in b)Object.prototype.hasOwnProperty.call(b,a)&&(e[a]=b[a]);for(u&&u(r);l.length;)l.shift()();return n.push.apply(n,d||[]),t()}function t(){for(var e,r=0;r<n.length;r++){for(var t=n[r],a=!0,o=1;o<t.length;o++)0!==c[t[o]]&&(a=!1);a&&(n.splice(r--,1),e=f(f.s=t[0]))}return e}var a={},c={11:0},n=[];function f(r){if(a[r])return a[r].exports;var t=a[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[],t=c[e];if(0!==t)if(t)r.push(t[2]);else{var a=new Promise(function(r,a){t=c[e]=[r,a]});r.push(t[2]=a);var n,o=document.createElement("script");o.charset="utf-8",o.timeout=120,f.nc&&o.setAttribute("nonce",f.nc),o.src=function(e){return f.p+""+({3:"common"}[e]||e)+"-es2015."+{0:"c7c5a6d51b98cb85b9fc",1:"bb4492eeabe1fe937ada",2:"51eb8544ea9a21f2874c",3:"388805227aa99c527fba",4:"f8ac5475bf103969b2d2",5:"90ea7bd4439d9749e052",6:"5fb726c0555664300974",7:"19ccb84e62e2ea874f53",8:"b901639e2aeff1358c3d",9:"b7bcad8238f58e214f03",10:"56da22458086513ba0c7",12:"be58ed0ef449008b932e",13:"343b0261a8b3b3f4a1fc",14:"b6619d7742671d2a37fb",15:"d8855701408b0e1d7a3e",16:"98fa59c2c96d2caac3c3",17:"7f60b56d1fd66d4d5544",18:"583f191cc7ad512ee262",19:"78ec0e9fd228b5104712",20:"90544c488f1f0900bab4",21:"63ed4e6b242fbc047bd6",22:"1e96ef651f96d51191e2",23:"6d3052555b4fac38f16d",28:"a2bf42f38e4dd771ccea",29:"18b515f07c88753c7eb6",30:"d4d3dc4101400cadf3f3",31:"e3ea815f75c19c217b7d",32:"57553995bff0ae518501",33:"da5ba1e5baa164921198",34:"87acbb95cfb824650157",35:"8f79ff8748d4ff06ab03",36:"e3a104020eeec02cb8c4",37:"3b472e6cf303201bbf2c",38:"39dbf43d46cdc94f78c6",39:"e5475ea4fb6ec5c60741",40:"47b2873a8439717af6a7",41:"69f2771002745c066976",42:"b590b92ede890155dcd6",43:"ad1d956bffba561ba64c",44:"3ef2c17996ed5be95ced",45:"3d65d27e0a7085e96356",46:"e4f0a5b127eae13c27c0",47:"c7d45334a70131f133b5"}[e]+".js"}(e);var b=new Error;n=function(r){o.onerror=o.onload=null,clearTimeout(d);var t=c[e];if(0!==t){if(t){var a=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;b.message="Loading chunk "+e+" failed.\n("+a+": "+n+")",b.name="ChunkLoadError",b.type=a,b.request=n,t[1](b)}c[e]=void 0}};var d=setTimeout(function(){n({type:"timeout",target:o})},12e4);o.onerror=o.onload=n,document.head.appendChild(o)}return Promise.all(r)},f.m=e,f.c=a,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var a in e)f.d(t,a,(function(r){return e[r]}).bind(null,a));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="",f.oe=function(e){throw console.error(e),e};var o=window.webpackJsonp=window.webpackJsonp||[],b=o.push.bind(o);o.push=r,o=o.slice();for(var d=0;d<o.length;d++)r(o[d]);var u=b;t()}([]);
1
+ !function(e){function r(r){for(var a,f,o=r[0],b=r[1],d=r[2],i=0,l=[];i<o.length;i++)f=o[i],Object.prototype.hasOwnProperty.call(c,f)&&c[f]&&l.push(c[f][0]),c[f]=0;for(a in b)Object.prototype.hasOwnProperty.call(b,a)&&(e[a]=b[a]);for(u&&u(r);l.length;)l.shift()();return n.push.apply(n,d||[]),t()}function t(){for(var e,r=0;r<n.length;r++){for(var t=n[r],a=!0,o=1;o<t.length;o++)0!==c[t[o]]&&(a=!1);a&&(n.splice(r--,1),e=f(f.s=t[0]))}return e}var a={},c={11:0},n=[];function f(r){if(a[r])return a[r].exports;var t=a[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[],t=c[e];if(0!==t)if(t)r.push(t[2]);else{var a=new Promise(function(r,a){t=c[e]=[r,a]});r.push(t[2]=a);var n,o=document.createElement("script");o.charset="utf-8",o.timeout=120,f.nc&&o.setAttribute("nonce",f.nc),o.src=function(e){return f.p+""+({3:"common"}[e]||e)+"-es2015."+{0:"c7c5a6d51b98cb85b9fc",1:"bb4492eeabe1fe937ada",2:"51eb8544ea9a21f2874c",3:"388805227aa99c527fba",4:"f8ac5475bf103969b2d2",5:"90ea7bd4439d9749e052",6:"5fb726c0555664300974",7:"19ccb84e62e2ea874f53",8:"b901639e2aeff1358c3d",9:"b7bcad8238f58e214f03",10:"56da22458086513ba0c7",12:"be58ed0ef449008b932e",13:"343b0261a8b3b3f4a1fc",14:"b6619d7742671d2a37fb",15:"d8855701408b0e1d7a3e",16:"98fa59c2c96d2caac3c3",17:"7f60b56d1fd66d4d5544",18:"503207073756a9c8211a",19:"78ec0e9fd228b5104712",20:"90544c488f1f0900bab4",21:"63ed4e6b242fbc047bd6",22:"1e96ef651f96d51191e2",23:"6d3052555b4fac38f16d",28:"a2bf42f38e4dd771ccea",29:"18b515f07c88753c7eb6",30:"d4d3dc4101400cadf3f3",31:"e3ea815f75c19c217b7d",32:"57553995bff0ae518501",33:"da5ba1e5baa164921198",34:"87acbb95cfb824650157",35:"8f79ff8748d4ff06ab03",36:"e3a104020eeec02cb8c4",37:"3b472e6cf303201bbf2c",38:"39dbf43d46cdc94f78c6",39:"e5475ea4fb6ec5c60741",40:"47b2873a8439717af6a7",41:"69f2771002745c066976",42:"b590b92ede890155dcd6",43:"ad1d956bffba561ba64c",44:"3ef2c17996ed5be95ced",45:"3d65d27e0a7085e96356",46:"e4f0a5b127eae13c27c0",47:"c7d45334a70131f133b5"}[e]+".js"}(e);var b=new Error;n=function(r){o.onerror=o.onload=null,clearTimeout(d);var t=c[e];if(0!==t){if(t){var a=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;b.message="Loading chunk "+e+" failed.\n("+a+": "+n+")",b.name="ChunkLoadError",b.type=a,b.request=n,t[1](b)}c[e]=void 0}};var d=setTimeout(function(){n({type:"timeout",target:o})},12e4);o.onerror=o.onload=n,document.head.appendChild(o)}return Promise.all(r)},f.m=e,f.c=a,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var a in e)f.d(t,a,(function(r){return e[r]}).bind(null,a));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="",f.oe=function(e){throw console.error(e),e};var o=window.webpackJsonp=window.webpackJsonp||[],b=o.push.bind(o);o.push=r,o=o.slice();for(var d=0;d<o.length;d++)r(o[d]);var u=b;t()}([]);
@@ -1 +1 @@
1
- !function(e){function r(r){for(var a,f,o=r[0],b=r[1],d=r[2],i=0,l=[];i<o.length;i++)f=o[i],Object.prototype.hasOwnProperty.call(c,f)&&c[f]&&l.push(c[f][0]),c[f]=0;for(a in b)Object.prototype.hasOwnProperty.call(b,a)&&(e[a]=b[a]);for(u&&u(r);l.length;)l.shift()();return n.push.apply(n,d||[]),t()}function t(){for(var e,r=0;r<n.length;r++){for(var t=n[r],a=!0,o=1;o<t.length;o++)0!==c[t[o]]&&(a=!1);a&&(n.splice(r--,1),e=f(f.s=t[0]))}return e}var a={},c={11:0},n=[];function f(r){if(a[r])return a[r].exports;var t=a[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[],t=c[e];if(0!==t)if(t)r.push(t[2]);else{var a=new Promise(function(r,a){t=c[e]=[r,a]});r.push(t[2]=a);var n,o=document.createElement("script");o.charset="utf-8",o.timeout=120,f.nc&&o.setAttribute("nonce",f.nc),o.src=function(e){return f.p+""+({3:"common"}[e]||e)+"-es5."+{0:"c7c5a6d51b98cb85b9fc",1:"bb4492eeabe1fe937ada",2:"51eb8544ea9a21f2874c",3:"388805227aa99c527fba",4:"f8ac5475bf103969b2d2",5:"90ea7bd4439d9749e052",6:"5fb726c0555664300974",7:"19ccb84e62e2ea874f53",8:"b901639e2aeff1358c3d",9:"b7bcad8238f58e214f03",10:"56da22458086513ba0c7",12:"be58ed0ef449008b932e",13:"343b0261a8b3b3f4a1fc",14:"b6619d7742671d2a37fb",15:"d8855701408b0e1d7a3e",16:"98fa59c2c96d2caac3c3",17:"7f60b56d1fd66d4d5544",18:"583f191cc7ad512ee262",19:"78ec0e9fd228b5104712",20:"90544c488f1f0900bab4",21:"63ed4e6b242fbc047bd6",22:"1e96ef651f96d51191e2",23:"6d3052555b4fac38f16d",28:"a2bf42f38e4dd771ccea",29:"18b515f07c88753c7eb6",30:"d4d3dc4101400cadf3f3",31:"e3ea815f75c19c217b7d",32:"57553995bff0ae518501",33:"da5ba1e5baa164921198",34:"87acbb95cfb824650157",35:"8f79ff8748d4ff06ab03",36:"e3a104020eeec02cb8c4",37:"3b472e6cf303201bbf2c",38:"39dbf43d46cdc94f78c6",39:"e5475ea4fb6ec5c60741",40:"47b2873a8439717af6a7",41:"69f2771002745c066976",42:"b590b92ede890155dcd6",43:"ad1d956bffba561ba64c",44:"3ef2c17996ed5be95ced",45:"3d65d27e0a7085e96356",46:"e4f0a5b127eae13c27c0",47:"c7d45334a70131f133b5"}[e]+".js"}(e);var b=new Error;n=function(r){o.onerror=o.onload=null,clearTimeout(d);var t=c[e];if(0!==t){if(t){var a=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;b.message="Loading chunk "+e+" failed.\n("+a+": "+n+")",b.name="ChunkLoadError",b.type=a,b.request=n,t[1](b)}c[e]=void 0}};var d=setTimeout(function(){n({type:"timeout",target:o})},12e4);o.onerror=o.onload=n,document.head.appendChild(o)}return Promise.all(r)},f.m=e,f.c=a,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var a in e)f.d(t,a,(function(r){return e[r]}).bind(null,a));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="",f.oe=function(e){throw console.error(e),e};var o=window.webpackJsonp=window.webpackJsonp||[],b=o.push.bind(o);o.push=r,o=o.slice();for(var d=0;d<o.length;d++)r(o[d]);var u=b;t()}([]);
1
+ !function(e){function r(r){for(var a,f,o=r[0],b=r[1],d=r[2],i=0,l=[];i<o.length;i++)f=o[i],Object.prototype.hasOwnProperty.call(c,f)&&c[f]&&l.push(c[f][0]),c[f]=0;for(a in b)Object.prototype.hasOwnProperty.call(b,a)&&(e[a]=b[a]);for(u&&u(r);l.length;)l.shift()();return n.push.apply(n,d||[]),t()}function t(){for(var e,r=0;r<n.length;r++){for(var t=n[r],a=!0,o=1;o<t.length;o++)0!==c[t[o]]&&(a=!1);a&&(n.splice(r--,1),e=f(f.s=t[0]))}return e}var a={},c={11:0},n=[];function f(r){if(a[r])return a[r].exports;var t=a[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,f),t.l=!0,t.exports}f.e=function(e){var r=[],t=c[e];if(0!==t)if(t)r.push(t[2]);else{var a=new Promise(function(r,a){t=c[e]=[r,a]});r.push(t[2]=a);var n,o=document.createElement("script");o.charset="utf-8",o.timeout=120,f.nc&&o.setAttribute("nonce",f.nc),o.src=function(e){return f.p+""+({3:"common"}[e]||e)+"-es5."+{0:"c7c5a6d51b98cb85b9fc",1:"bb4492eeabe1fe937ada",2:"51eb8544ea9a21f2874c",3:"388805227aa99c527fba",4:"f8ac5475bf103969b2d2",5:"90ea7bd4439d9749e052",6:"5fb726c0555664300974",7:"19ccb84e62e2ea874f53",8:"b901639e2aeff1358c3d",9:"b7bcad8238f58e214f03",10:"56da22458086513ba0c7",12:"be58ed0ef449008b932e",13:"343b0261a8b3b3f4a1fc",14:"b6619d7742671d2a37fb",15:"d8855701408b0e1d7a3e",16:"98fa59c2c96d2caac3c3",17:"7f60b56d1fd66d4d5544",18:"503207073756a9c8211a",19:"78ec0e9fd228b5104712",20:"90544c488f1f0900bab4",21:"63ed4e6b242fbc047bd6",22:"1e96ef651f96d51191e2",23:"6d3052555b4fac38f16d",28:"a2bf42f38e4dd771ccea",29:"18b515f07c88753c7eb6",30:"d4d3dc4101400cadf3f3",31:"e3ea815f75c19c217b7d",32:"57553995bff0ae518501",33:"da5ba1e5baa164921198",34:"87acbb95cfb824650157",35:"8f79ff8748d4ff06ab03",36:"e3a104020eeec02cb8c4",37:"3b472e6cf303201bbf2c",38:"39dbf43d46cdc94f78c6",39:"e5475ea4fb6ec5c60741",40:"47b2873a8439717af6a7",41:"69f2771002745c066976",42:"b590b92ede890155dcd6",43:"ad1d956bffba561ba64c",44:"3ef2c17996ed5be95ced",45:"3d65d27e0a7085e96356",46:"e4f0a5b127eae13c27c0",47:"c7d45334a70131f133b5"}[e]+".js"}(e);var b=new Error;n=function(r){o.onerror=o.onload=null,clearTimeout(d);var t=c[e];if(0!==t){if(t){var a=r&&("load"===r.type?"missing":r.type),n=r&&r.target&&r.target.src;b.message="Loading chunk "+e+" failed.\n("+a+": "+n+")",b.name="ChunkLoadError",b.type=a,b.request=n,t[1](b)}c[e]=void 0}};var d=setTimeout(function(){n({type:"timeout",target:o})},12e4);o.onerror=o.onload=n,document.head.appendChild(o)}return Promise.all(r)},f.m=e,f.c=a,f.d=function(e,r,t){f.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},f.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},f.t=function(e,r){if(1&r&&(e=f(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(f.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var a in e)f.d(t,a,(function(r){return e[r]}).bind(null,a));return t},f.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return f.d(r,"a",r),r},f.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},f.p="",f.oe=function(e){throw console.error(e),e};var o=window.webpackJsonp=window.webpackJsonp||[],b=o.push.bind(o);o.push=r,o=o.slice();for(var d=0;d<o.length;d++)r(o[d]);var u=b;t()}([]);
@@ -1,6 +1,7 @@
1
1
  import copy
2
- from pathlib import Path
3
2
  import pdb
3
+
4
+ from pathlib import Path
4
5
  from pprint import pprint
5
6
  from typing import Dict
6
7
 
@@ -124,7 +124,7 @@ class TestScaffoldE2e():
124
124
  # Add user defined Docker Compose file for the local service
125
125
  shutil.copyfile(local_service_mock_docker_compose_path, destination_path)
126
126
 
127
- # Record workflow doesn't have a fixtures folder
127
+ # Record workflow doesn't have a public folder
128
128
 
129
129
  # Generate certs
130
130
  ScaffoldCliInvoker.cli_app_mkcert(runner, app_dir_path)
@@ -249,7 +249,7 @@ class TestScaffoldE2e():
249
249
  'service_name': external_service_docker_compose.service_name
250
250
  }
251
251
  command = ServiceWorkflowValidateCommand(app, **config)
252
- with open(f"{command.fixtures_dir_path}/shared_file.txt", 'w') as file:
252
+ with open(f"{command.public_dir_path}/shared_file.txt", 'w') as file:
253
253
  file.write('this is a shared file')
254
254
 
255
255
  ScaffoldCliInvoker.cli_workflow_up(runner, app_dir_path, target_workflow_name=target_workflow_name)
@@ -5,7 +5,7 @@ import time
5
5
  from typing import List
6
6
 
7
7
  from stoobly_agent.app.models.factories.resource.local_db.helpers.tiebreak_scenario_request import (
8
- access_request, generate_session_id, reset as reset_tiebreak, tiebreak_scenario_request
8
+ access_request, generate_session_id, reset_sessions, tiebreak_scenario_request
9
9
  )
10
10
  from stoobly_agent.lib.cache import Cache
11
11
  from stoobly_agent.lib.orm.request import Request
@@ -92,7 +92,7 @@ class TestTiebreakScenarioRequest():
92
92
  request = tiebreak_scenario_request(session_id, requests)
93
93
  assert request.id == 2
94
94
 
95
- class TestWhenReset():
95
+ class TestWhenResetSessions():
96
96
  @pytest.fixture(scope='class')
97
97
  def created_request_one(self):
98
98
  return RequestMock(1)
@@ -105,7 +105,7 @@ class TestTiebreakScenarioRequest():
105
105
  def test_it_resets(self, cache: Cache, created_request_one: Request):
106
106
  cache.write('persists', 1)
107
107
  access_request('1', created_request_one.id)
108
- reset_tiebreak()
108
+ reset_sessions()
109
109
 
110
110
  assert cache.read('persists') != None
111
- assert len(cache.read_all()) == 1
111
+ assert len(cache.read_all()) == 1
@@ -1 +1 @@
1
- 1.4.1
1
+ 1.5.0
@@ -25,75 +25,144 @@ def settings():
25
25
  return reset()
26
26
 
27
27
  class TestEvalFixturesService():
28
- @pytest.fixture(scope='class')
29
- def request_method(self):
30
- return 'POST'
31
-
32
- @pytest.fixture(scope='class')
33
- def request_url(self):
34
- return 'https://petstore.swagger.io/index.html'
35
-
36
- @pytest.fixture(scope='class')
37
- def created_request(
38
- self, settings: Settings, request_method: str, request_url: str
39
- ):
40
- status = RequestBuilder(
41
- method=request_method,
42
- response_body='',
43
- status_code=200,
44
- url=request_url,
45
- ).with_settings(settings).build()[1]
46
- assert status == 200
47
-
48
- return Request.last()
49
-
50
- @pytest.fixture(scope='class')
51
- def public_directory(self):
52
- tmp_dir_path = DataDir.instance().tmp_dir_path
53
- public_dir_path = os.path.join(tmp_dir_path, 'public')
54
- if not os.path.exists(public_dir_path):
55
- os.mkdir(public_dir_path)
56
- return public_dir_path
57
-
58
- @pytest.fixture(scope='class')
59
- def index_file_contents(self):
60
- return b'Hello World!'
61
-
62
- @pytest.fixture(autouse=True, scope='class')
63
- def index_file_path(self, public_directory: str, index_file_contents: str):
64
- path = os.path.join(public_directory, 'index.html')
65
- with open(path, 'wb') as fp:
66
- fp.write(index_file_contents)
67
- return path
68
-
69
- @pytest.fixture(scope='class')
70
- def response_fixtures(self, request_method: str, index_file_path: str) -> Fixtures:
71
- fixtures = {}
72
- fixtures[request_method] = {
73
- '/index.html': {
74
- 'headers': {
75
- 'Content-Length': '1',
76
- },
77
- 'path': index_file_path,
28
+ class TestResponseFixtures():
29
+ @pytest.fixture(scope='class')
30
+ def request_method(self):
31
+ return 'POST'
32
+
33
+ @pytest.fixture(scope='class')
34
+ def request_url(self):
35
+ return 'https://petstore.swagger.io/404.html'
36
+
37
+ @pytest.fixture(scope='class')
38
+ def created_request(
39
+ self, settings: Settings, request_method: str, request_url: str
40
+ ):
41
+ status = RequestBuilder(
42
+ method=request_method,
43
+ response_body='',
44
+ status_code=200,
45
+ url=request_url,
46
+ ).with_settings(settings).build()[1]
47
+ assert status == 200
48
+
49
+ return Request.last()
50
+
51
+ @pytest.fixture(scope='class')
52
+ def not_found_file_contents(self):
53
+ return b'Not Found'
54
+
55
+ @pytest.fixture(scope='class')
56
+ def public_directory(self):
57
+ tmp_dir_path = DataDir.instance().tmp_dir_path
58
+ public_dir_path = os.path.join(tmp_dir_path, 'public')
59
+ if not os.path.exists(public_dir_path):
60
+ os.mkdir(public_dir_path)
61
+ return public_dir_path
62
+
63
+ @pytest.fixture(autouse=True, scope='class')
64
+ def not_found_file_path(self, public_directory: str, not_found_file_contents: str):
65
+ path = os.path.join(public_directory, '404.html')
66
+ with open(path, 'wb') as fp:
67
+ fp.write(not_found_file_contents)
68
+ return path
69
+
70
+ @pytest.fixture(scope='class')
71
+ def response_fixtures(self, request_method: str, not_found_file_path: str) -> Fixtures:
72
+ fixtures = {}
73
+ fixtures[request_method] = {
74
+ '/404.html': {
75
+ 'headers': {
76
+ 'test': '1',
77
+ },
78
+ 'path': not_found_file_path,
79
+ 'status_code': 404,
80
+ }
78
81
  }
79
- }
80
- return fixtures
81
-
82
- @pytest.fixture()
83
- def mitmproxy_request(self, created_request: Request) -> MitmproxyRequest:
84
- return MitmproxyRequestAdapter(created_request).adapt()
85
-
86
- def test_it_evaluates_response_fixture(
87
- self, mitmproxy_request: MitmproxyRequest, response_fixtures: Fixtures, index_file_contents: str
88
- ):
89
- res: requests.Response = eval_fixtures(mitmproxy_request, response_fixtures=response_fixtures)
90
- assert res
91
- assert res.raw.read() == index_file_contents
92
- assert res.headers['Content-Length'] == '1'
93
-
94
- def test_it_evaluates_public_directory(
95
- self, mitmproxy_request: MitmproxyRequest, public_directory: str, index_file_contents: str
96
- ):
97
- res: requests.Response = eval_fixtures(mitmproxy_request, public_directory_path=public_directory)
98
- assert res
99
- assert res.raw.read() == index_file_contents
82
+ return fixtures
83
+
84
+ @pytest.fixture()
85
+ def mitmproxy_request(self, created_request: Request) -> MitmproxyRequest:
86
+ return MitmproxyRequestAdapter(created_request).adapt()
87
+
88
+ @pytest.fixture()
89
+ def fixtures_response(self, mitmproxy_request: MitmproxyRequest, response_fixtures: Fixtures):
90
+ res: requests.Response = eval_fixtures(mitmproxy_request, response_fixtures=response_fixtures)
91
+ assert res != None
92
+ return res
93
+
94
+ def test_it_sets_response(
95
+ self, fixtures_response: requests.Response, not_found_file_contents: str
96
+ ):
97
+ assert fixtures_response.raw.read() == not_found_file_contents
98
+
99
+ def test_it_sets_headers(self, fixtures_response: requests.Response):
100
+ assert fixtures_response.headers['test'] == '1'
101
+ assert fixtures_response.headers['Content-Type'] == 'text/html'
102
+
103
+ def test_it_sets_status_code(self, fixtures_response: requests.Response):
104
+ assert fixtures_response.status_code == 404
105
+
106
+ class TestPublicDirectory():
107
+ @pytest.fixture(scope='class')
108
+ def request_method(self):
109
+ return 'GET'
110
+
111
+ @pytest.fixture(scope='class')
112
+ def request_url(self):
113
+ return 'https://petstore.swagger.io'
114
+
115
+ @pytest.fixture(scope='class')
116
+ def created_request(
117
+ self, settings: Settings, request_method: str, request_url: str
118
+ ):
119
+ status = RequestBuilder(
120
+ method=request_method,
121
+ request_headers={'accept': 'text/html;q=0.1,application/json;q=0.9'},
122
+ response_body='',
123
+ status_code=200,
124
+ url=request_url,
125
+ ).with_settings(settings).build()[1]
126
+ assert status == 200
127
+
128
+ return Request.last()
129
+
130
+ @pytest.fixture()
131
+ def mitmproxy_request(self, created_request: Request) -> MitmproxyRequest:
132
+ return MitmproxyRequestAdapter(created_request).adapt()
133
+
134
+ @pytest.fixture(scope='class')
135
+ def public_directory(self):
136
+ tmp_dir_path = DataDir.instance().tmp_dir_path
137
+ public_dir_path = os.path.join(tmp_dir_path, 'public')
138
+ if not os.path.exists(public_dir_path):
139
+ os.mkdir(public_dir_path)
140
+ return public_dir_path
141
+
142
+ @pytest.fixture(scope='class')
143
+ def index_file_contents(self):
144
+ return b'Hello World!'
145
+
146
+ @pytest.fixture(autouse=True, scope='class')
147
+ def index_file_path(self, public_directory: str, index_file_contents: str):
148
+ path = os.path.join(public_directory, 'index.html')
149
+ with open(path, 'wb') as fp:
150
+ fp.write(index_file_contents)
151
+ return path
152
+
153
+ @pytest.fixture()
154
+ def public_directory_response(self, mitmproxy_request: MitmproxyRequest, public_directory: str):
155
+ res: requests.Response = eval_fixtures(mitmproxy_request, public_directory_path=public_directory)
156
+ assert res != None
157
+ return res
158
+
159
+ def test_it_sets_contents(
160
+ self, public_directory_response: requests.Response, index_file_contents: str
161
+ ):
162
+ assert public_directory_response.raw.read() == index_file_contents
163
+
164
+ def test_it_headers(self, public_directory_response: requests.Response):
165
+ assert public_directory_response.headers['Content-Type'] == 'text/html'
166
+
167
+ def test_it_sets_status_code(self, public_directory_response: requests.Response):
168
+ assert public_directory_response.status_code == 200
@@ -0,0 +1,66 @@
1
+ import pdb
2
+ import pytest
3
+
4
+ from click.testing import CliRunner
5
+ from pathlib import Path
6
+
7
+ from stoobly_agent.cli import mock, record, request
8
+ from stoobly_agent.lib.orm.request import Request
9
+ from stoobly_agent.test.test_helper import DETERMINISTIC_GET_REQUEST_URL, reset
10
+
11
+ @pytest.fixture(scope='module')
12
+ def runner():
13
+ return CliRunner()
14
+
15
+ class TestLifecycleHooks():
16
+ @pytest.fixture(scope='class', autouse=True)
17
+ def settings(self):
18
+ return reset()
19
+
20
+ @pytest.fixture(scope='class')
21
+ def lifecycle_hooks_path(self):
22
+ return str(Path(__file__).parent.parent / 'mock_data' / 'lifecycle_hooks.py')
23
+
24
+ @pytest.fixture(scope='class')
25
+ def record_result(self, runner: CliRunner, lifecycle_hooks_path: str):
26
+ record_result = runner.invoke(record, [
27
+ '--lifecycle-hooks-path', lifecycle_hooks_path, '--output', '/dev/null', DETERMINISTIC_GET_REQUEST_URL
28
+ ])
29
+ assert record_result.exit_code == 0
30
+ return record_result
31
+
32
+ @pytest.fixture(scope='class')
33
+ def recorded_request(self):
34
+ return Request.last()
35
+
36
+ @pytest.fixture(scope='class')
37
+ def mock_result(self, runner: CliRunner, lifecycle_hooks_path: str):
38
+ mock_result = runner.invoke(mock, [
39
+ '--lifecycle-hooks-path', lifecycle_hooks_path, '--output', '/dev/null', DETERMINISTIC_GET_REQUEST_URL
40
+ ])
41
+ assert mock_result.exit_code == 0
42
+ return mock_result
43
+
44
+ @pytest.fixture(scope='class')
45
+ def test_result(self, runner: CliRunner, lifecycle_hooks_path: str, recorded_request: Request):
46
+ test_result = runner.invoke(request, [
47
+ 'test', '--format', 'json', '--lifecycle-hooks-path', lifecycle_hooks_path, recorded_request.key()
48
+ ])
49
+ assert test_result.exit_code == 0
50
+ return test_result
51
+
52
+ def test_calls_record_hooks(self, record_result):
53
+ expected_stdout = ['before_request', 'before_record', 'after_record', 'before_response']
54
+ assert record_result.stdout.strip() == "\n".join(expected_stdout)
55
+
56
+ def test_calls_mock_hooks(self, mock_result):
57
+ expected_stdout = ['before_request', 'before_mock', 'after_mock', 'before_response']
58
+ assert mock_result.stdout.strip() == "\n".join(expected_stdout)
59
+
60
+ def test_calls_test_hooks(self, test_result):
61
+ expected_stdout = [
62
+ 'before_request', 'before_replay', 'after_replay', 'before_mock', 'after_mock', 'before_test', 'after_test', 'before_response'
63
+ ]
64
+ stdout = test_result.stdout
65
+ lifecycle_hooks_output = stdout.split('{')[0]
66
+ assert lifecycle_hooks_output.strip() == "\n".join(expected_stdout)
@@ -0,0 +1,5 @@
1
+ from stoobly_agent.app.proxy.context import InterceptContext
2
+ from stoobly_agent.config.constants.custom_headers import MOCK_REQUEST_ID
3
+
4
+ def handle_before_response(context: InterceptContext):
5
+ print(context.flow.response.headers[MOCK_REQUEST_ID], end='')
@@ -0,0 +1,62 @@
1
+ import pdb
2
+ import pytest
3
+
4
+ from click.testing import CliRunner
5
+ from pathlib import Path
6
+
7
+ from stoobly_agent.test.test_helper import DETERMINISTIC_GET_REQUEST_URL, NON_DETERMINISTIC_GET_REQUEST_URL
8
+
9
+ from stoobly_agent.config.constants.custom_headers import SESSION_ID
10
+ from stoobly_agent.cli import mock, record, scenario
11
+ from stoobly_agent.lib.api.keys.scenario_key import ScenarioKey
12
+ from stoobly_agent.lib.orm.request import Request
13
+
14
+ @pytest.fixture(scope='module')
15
+ def runner():
16
+ return CliRunner()
17
+
18
+ class TestMocking():
19
+ @pytest.fixture(scope='class')
20
+ def lifecycle_hooks_path(self):
21
+ return str(Path(__file__).parent / 'mock_scenario_lifecycle_hooks.py')
22
+
23
+ class TestScenario():
24
+ @pytest.fixture(scope='class')
25
+ def scenario_key(self, runner: CliRunner):
26
+ res = runner.invoke(scenario, ['create', '--select', 'key', '--without-headers', 'test-scenario'])
27
+ assert res.exit_code == 0
28
+ return ScenarioKey(res.stdout.strip()).raw
29
+
30
+ @pytest.fixture(autouse=True, scope='class')
31
+ def recorded_request1(self, runner: CliRunner, scenario_key: str):
32
+ record_result = runner.invoke(record, ['--scenario-key', scenario_key, DETERMINISTIC_GET_REQUEST_URL])
33
+ assert record_result.exit_code == 0
34
+ return Request.last()
35
+
36
+ @pytest.fixture(autouse=True, scope='class')
37
+ def recorded_request2(self, runner: CliRunner, scenario_key: str):
38
+ record_result = runner.invoke(record, ['--scenario-key', scenario_key, DETERMINISTIC_GET_REQUEST_URL])
39
+ assert record_result.exit_code == 0
40
+ return Request.last()
41
+
42
+ def test_it_does_not_mocks(self, runner: CliRunner, scenario_key: str):
43
+ mock_result = runner.invoke(mock, ['--scenario-key', scenario_key, NON_DETERMINISTIC_GET_REQUEST_URL])
44
+ assert mock_result.exit_code == 1
45
+
46
+ def test_it_mocks(self, runner: CliRunner, scenario_key: str):
47
+ mock_result = runner.invoke(mock, ['--scenario-key', scenario_key, DETERMINISTIC_GET_REQUEST_URL])
48
+ assert mock_result.exit_code == 0
49
+
50
+ def test_it_mocks_in_order(
51
+ self, runner: CliRunner, lifecycle_hooks_path: str, recorded_request1: Request, recorded_request2: Request, scenario_key: str
52
+ ):
53
+ session_id = 'test'
54
+ args = [
55
+ '--lifecycle-hooks-path', lifecycle_hooks_path, '--scenario-key', scenario_key, '--output', '/dev/null',
56
+ '-H', f"{SESSION_ID}: {session_id}", DETERMINISTIC_GET_REQUEST_URL
57
+ ]
58
+ mock_result = runner.invoke(mock, args)
59
+ assert int(mock_result.stdout) == recorded_request1.id
60
+
61
+ mock_result = runner.invoke(mock, args)
62
+ assert int(mock_result.stdout) == recorded_request2.id
@@ -8,10 +8,10 @@ from stoobly_agent.test.test_helper import DETERMINISTIC_GET_REQUEST_URL, reset
8
8
 
9
9
  from stoobly_agent.config.constants import mode
10
10
  from stoobly_agent.app.settings.constants import request_component
11
- from stoobly_agent.cli import config, mock, record, scenario
12
- from stoobly_agent.lib.api.keys.scenario_key import ScenarioKey
11
+ from stoobly_agent.cli import config, mock, record
12
+ from stoobly_agent.lib.orm.request import Request
13
13
 
14
- @pytest.fixture()
14
+ @pytest.fixture(scope='module')
15
15
  def runner():
16
16
  return CliRunner()
17
17
 
@@ -23,46 +23,60 @@ class TestMocking():
23
23
  return reset()
24
24
 
25
25
  class TestWhenHeaders():
26
+ header_name = 'foo'
27
+ header_value = 'bar'
28
+ url = DETERMINISTIC_GET_REQUEST_URL
26
29
 
27
- def test_it_rewrites(self, runner: CliRunner):
28
- header_name = 'foo'
29
- header_value = 'bar'
30
-
31
- url = DETERMINISTIC_GET_REQUEST_URL
32
- record_result = runner.invoke(record, [url, '-H', f"{header_name}: {header_value}"])
30
+ @pytest.fixture(autouse=True, scope='class')
31
+ def recorded_request(self, runner: CliRunner):
32
+ record_result = runner.invoke(record, [self.url, '-H', f"{self.header_name}: {self.header_value}"])
33
33
  assert record_result.exit_code == 0
34
+ return Request.last()
35
+
36
+ def test_it_ignores_headers_default(self, runner: CliRunner):
37
+ # Expect to fail since we have not set up rewrite rule for mock mode
38
+ mock_result = runner.invoke(mock, [self.url])
39
+ assert mock_result.exit_code == 0
34
40
 
41
+ def test_it_fails_when_enabled(self, runner: CliRunner):
35
42
  # Enforce matching by headers only
36
43
  match_result = runner.invoke(config, [
37
44
  'match', 'set',
38
45
  '--method', 'GET', '--mode', mode.MOCK, '--pattern', '.*?', '--component', request_component.HEADER
39
46
  ])
40
47
  assert match_result.exit_code == 0
41
-
48
+
42
49
  # Expect to fail since we have not set up rewrite rule for mock mode
43
- mock_result = runner.invoke(mock, [url])
50
+ mock_result = runner.invoke(mock, [self.url])
44
51
  assert mock_result.exit_code == 1
45
52
 
53
+ def test_it_succeeds_after_rewrite(self, runner: CliRunner):
46
54
  rewrite_result = runner.invoke(config, [
47
55
  'rewrite', 'set',
48
- '--method', 'GET', '--mode', mode.MOCK, '--name', header_name, '--value', header_value, '--pattern', '.*?', '--type', request_component.HEADER
56
+ '--method', 'GET', '--mode', mode.MOCK, '--name', self.header_name, '--value', self.header_value, '--pattern', '.*?', '--type', request_component.HEADER
49
57
  ]
50
58
  )
51
59
  assert rewrite_result.exit_code == 0
52
60
 
53
- mock_result = runner.invoke(mock, [url])
61
+ mock_result = runner.invoke(mock, [self.url])
54
62
  assert mock_result.exit_code == 0
55
63
 
56
64
  class TestWhenQueryParams():
65
+ query_param_name = 'foo'
66
+ query_param_value = 'bar'
67
+ url = DETERMINISTIC_GET_REQUEST_URL
57
68
 
58
- def test_it_rewrites(self, runner: CliRunner):
59
- query_param_name = 'foo'
60
- query_param_value = 'bar'
61
-
62
- url = DETERMINISTIC_GET_REQUEST_URL
63
- record_result = runner.invoke(record, [f"{url}?{query_param_name}={query_param_value}"])
69
+ @pytest.fixture(autouse=True, scope='class')
70
+ def recorded_request(self, runner: CliRunner):
71
+ record_result = runner.invoke(record, [f"{self.url}?{self.query_param_name}={self.query_param_value}"])
64
72
  assert record_result.exit_code == 0
73
+ return Request.last()
65
74
 
75
+ def test_it_ignores_query_params_by_default(self, runner: CliRunner):
76
+ mock_result = runner.invoke(mock, [self.url])
77
+ assert mock_result.exit_code == 0
78
+
79
+ def test_it_fails_when_enabled(self, runner: CliRunner):
66
80
  # Enforce matching by query params only
67
81
  match_result = runner.invoke(config, [
68
82
  'match', 'set',
@@ -71,34 +85,42 @@ class TestMocking():
71
85
  assert match_result.exit_code == 0
72
86
 
73
87
  # Expect to fail since we have not set up rewrite rule for mock mode
74
- mock_result = runner.invoke(mock, [url])
88
+ mock_result = runner.invoke(mock, [self.url])
75
89
  assert mock_result.exit_code == 1
76
90
 
91
+ def test_it_succeeds_after_rewrites(self, runner: CliRunner):
77
92
  rewrite_result = runner.invoke(config, [
78
93
  'rewrite', 'set',
79
- '--method', 'GET', '--mode', mode.MOCK, '--name', query_param_name, '--value', query_param_value, '--pattern', '.*?', '--type', request_component.QUERY_PARAM
94
+ '--method', 'GET', '--mode', mode.MOCK, '--name', self.query_param_name, '--value', self.query_param_value, '--pattern', '.*?', '--type', request_component.QUERY_PARAM
80
95
  ]
81
96
  )
82
97
  assert rewrite_result.exit_code == 0
83
98
 
84
- mock_result = runner.invoke(mock, [url])
99
+ mock_result = runner.invoke(mock, [self.url])
85
100
  assert mock_result.exit_code == 0
86
101
 
87
102
  class TestWhenBodyParams():
103
+ body_param_name = 'foo'
104
+ body_param_value = 'bar'
105
+ url = DETERMINISTIC_GET_REQUEST_URL
88
106
 
89
- def test_it_rewrites(self, runner: CliRunner):
90
- body_param_name = 'foo'
91
- body_param_value = 'bar'
92
-
107
+ @pytest.fixture(autouse=True, scope='class')
108
+ def recorded_request(self, runner: CliRunner):
93
109
  content = {}
94
- content[body_param_name] = body_param_value
110
+ content[self.body_param_name] = self.body_param_value
95
111
  body = json.dumps(content)
96
112
 
97
113
  url = DETERMINISTIC_GET_REQUEST_URL
98
114
  record_result = runner.invoke(record, [url, '-d', body, '-H', 'Content-Type: application/json'])
99
115
  assert record_result.exit_code == 0
116
+ return Request.last()
100
117
 
101
- # Enforce matching by query params only
118
+ def test_it_ignores_body_params_by_default(self, runner: CliRunner):
119
+ mock_result = runner.invoke(mock, [self.url])
120
+ assert mock_result.exit_code == 0
121
+
122
+ def test_it_fails_when_enabled(self, runner: CliRunner):
123
+ # Enforce matching by bodyy params only
102
124
  match_result = runner.invoke(config, [
103
125
  'match', 'set',
104
126
  '--method', 'GET', '--mode', mode.MOCK, '--pattern', '.*?', '--component', request_component.BODY_PARAM
@@ -106,23 +128,17 @@ class TestMocking():
106
128
  assert match_result.exit_code == 0
107
129
 
108
130
  # Expect to fail since we have not set up rewrite rule for mock mode
109
- mock_result = runner.invoke(mock, [url])
131
+ mock_result = runner.invoke(mock, [self.url])
110
132
  assert mock_result.exit_code == 1
111
133
 
134
+ def test_it_succeeds_after_rewrites(self, runner: CliRunner):
112
135
  rewrite_result = runner.invoke(config, [
113
136
  'rewrite', 'set',
114
- '--method', 'GET', '--mode', mode.MOCK, '--name', body_param_name, '--value', body_param_value, '--pattern', '.*?', '--type', request_component.BODY_PARAM
137
+ '--method', 'GET', '--mode', mode.MOCK, '--name', self.body_param_name, '--value', self.body_param_value, '--pattern', '.*?', '--type', request_component.BODY_PARAM
115
138
  ]
116
139
  )
117
140
  assert rewrite_result.exit_code == 0
118
141
 
119
- mock_result = runner.invoke(mock, [url])
142
+ mock_result = runner.invoke(mock, [self.url])
120
143
  assert mock_result.exit_code == 0
121
144
 
122
- class TestScenario():
123
-
124
- @pytest.fixture
125
- def scenario_key(self, runner: CliRunner):
126
- res = runner.invoke(scenario, ['create', '--select', 'key', '--without-headers', 'test-scenario'])
127
- assert res.exit_code == 0
128
- return ScenarioKey(res.stdout.strip())