@internetarchive/fetch-handler 1.0.1 → 1.1.0-webdev-7731.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 (87) hide show
  1. package/.github/workflows/ci.yml +5 -0
  2. package/.github/workflows/gh-pages-main.yml +4 -0
  3. package/.github/workflows/pr-preview.yml +4 -0
  4. package/README.md +5 -5
  5. package/demo/app-root.ts +1 -1
  6. package/dist/demo/app-root.d.ts +1 -1
  7. package/dist/demo/app-root.js +1 -1
  8. package/dist/demo/app-root.js.map +1 -1
  9. package/dist/index.d.ts +6 -1
  10. package/dist/index.js +4 -1
  11. package/dist/index.js.map +1 -1
  12. package/dist/src/fetch-handler-interface.d.ts +16 -3
  13. package/dist/src/fetch-handler-interface.js.map +1 -1
  14. package/dist/src/{ia-fetch-handler.d.ts → fetch-handler.d.ts} +10 -2
  15. package/dist/src/{ia-fetch-handler.js → fetch-handler.js} +13 -16
  16. package/dist/src/fetch-handler.js.map +1 -0
  17. package/dist/src/fetch-options.d.ts +5 -0
  18. package/dist/src/fetch-options.js +2 -0
  19. package/dist/src/fetch-options.js.map +1 -0
  20. package/dist/src/fetch-retry/configuration/default-retry-configuration.d.ts +10 -0
  21. package/dist/src/fetch-retry/configuration/default-retry-configuration.js +20 -0
  22. package/dist/src/fetch-retry/configuration/default-retry-configuration.js.map +1 -0
  23. package/dist/src/fetch-retry/configuration/milliseconds.d.ts +1 -0
  24. package/dist/src/fetch-retry/configuration/milliseconds.js +2 -0
  25. package/dist/src/fetch-retry/configuration/milliseconds.js.map +1 -0
  26. package/dist/src/fetch-retry/configuration/no-retry-configuration.d.ts +6 -0
  27. package/dist/src/fetch-retry/configuration/no-retry-configuration.js +9 -0
  28. package/dist/src/fetch-retry/configuration/no-retry-configuration.js.map +1 -0
  29. package/dist/src/fetch-retry/configuration/retry-configuring.d.ts +5 -0
  30. package/dist/src/fetch-retry/configuration/retry-configuring.js +2 -0
  31. package/dist/src/fetch-retry/configuration/retry-configuring.js.map +1 -0
  32. package/dist/src/{utils → fetch-retry}/fetch-retrier.d.ts +11 -13
  33. package/dist/src/fetch-retry/fetch-retrier.js +97 -0
  34. package/dist/src/fetch-retry/fetch-retrier.js.map +1 -0
  35. package/dist/src/fetch-retry/legacy-args.d.ts +2 -0
  36. package/dist/src/fetch-retry/legacy-args.js +11 -0
  37. package/dist/src/fetch-retry/legacy-args.js.map +1 -0
  38. package/dist/test/default-retry-config.test.js +30 -0
  39. package/dist/test/default-retry-config.test.js.map +1 -0
  40. package/dist/test/fetch-handler.test.d.ts +1 -0
  41. package/dist/test/fetch-handler.test.js +87 -0
  42. package/dist/test/fetch-handler.test.js.map +1 -0
  43. package/dist/test/fetch-retrier.test.js +76 -42
  44. package/dist/test/fetch-retrier.test.js.map +1 -1
  45. package/dist/test/legacy-args.test.d.ts +1 -0
  46. package/dist/test/legacy-args.test.js +21 -0
  47. package/dist/test/legacy-args.test.js.map +1 -0
  48. package/dist/test/mocks/mock-fetch-retrier.d.ts +10 -0
  49. package/dist/test/mocks/mock-fetch-retrier.js +11 -0
  50. package/dist/test/mocks/mock-fetch-retrier.js.map +1 -0
  51. package/dist/test/mocks/mock-retry-config.d.ts +7 -0
  52. package/dist/test/mocks/mock-retry-config.js +13 -0
  53. package/dist/test/mocks/mock-retry-config.js.map +1 -0
  54. package/dist/test/no-retry-config.test.d.ts +1 -0
  55. package/dist/test/no-retry-config.test.js +13 -0
  56. package/dist/test/no-retry-config.test.js.map +1 -0
  57. package/dist/test/retrier-legacy-args.test.d.ts +1 -0
  58. package/dist/test/retrier-legacy-args.test.js +27 -0
  59. package/dist/test/retrier-legacy-args.test.js.map +1 -0
  60. package/index.ts +9 -1
  61. package/package.json +5 -5
  62. package/src/fetch-handler-interface.ts +23 -4
  63. package/src/{ia-fetch-handler.ts → fetch-handler.ts} +27 -15
  64. package/src/fetch-options.ts +6 -0
  65. package/src/fetch-retry/configuration/default-retry-configuration.ts +23 -0
  66. package/src/fetch-retry/configuration/milliseconds.ts +1 -0
  67. package/src/fetch-retry/configuration/no-retry-configuration.ts +12 -0
  68. package/src/fetch-retry/configuration/retry-configuring.ts +11 -0
  69. package/src/fetch-retry/fetch-retrier.ts +146 -0
  70. package/src/fetch-retry/legacy-args.ts +13 -0
  71. package/test/default-retry-config.test.ts +34 -0
  72. package/test/fetch-handler.test.ts +99 -0
  73. package/test/fetch-retrier.test.ts +87 -46
  74. package/test/legacy-args.test.ts +24 -0
  75. package/test/mocks/mock-fetch-retrier.ts +22 -0
  76. package/test/mocks/mock-retry-config.ts +19 -0
  77. package/test/no-retry-config.test.ts +14 -0
  78. package/test/retrier-legacy-args.test.ts +28 -0
  79. package/web-test-runner.config.mjs +5 -3
  80. package/dist/src/ia-fetch-handler.js.map +0 -1
  81. package/dist/src/utils/fetch-retrier.js +0 -94
  82. package/dist/src/utils/fetch-retrier.js.map +0 -1
  83. package/dist/test/ia-fetch-handler.test.js +0 -50
  84. package/dist/test/ia-fetch-handler.test.js.map +0 -1
  85. package/src/utils/fetch-retrier.ts +0 -141
  86. package/test/ia-fetch-handler.test.ts +0 -66
  87. /package/dist/test/{ia-fetch-handler.test.d.ts → default-retry-config.test.d.ts} +0 -0
@@ -0,0 +1,30 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { DefaultRetryConfiguration } from '../src/fetch-retry/configuration/default-retry-configuration';
3
+ describe('DefaultRetryConfiguration', () => {
4
+ it('should not retry on null response', async () => {
5
+ const config = new DefaultRetryConfiguration();
6
+ expect(config.shouldRetry(null, 1)).to.be.false;
7
+ });
8
+ it('should not retry after max retries exceeded', async () => {
9
+ const config = new DefaultRetryConfiguration({ maxRetries: 2 });
10
+ const mockResponse = new Response(null, { status: 500 });
11
+ expect(config.shouldRetry(mockResponse, 3)).to.be.false;
12
+ });
13
+ it('should retry on 5xx status codes', async () => {
14
+ const config = new DefaultRetryConfiguration();
15
+ const mockResponse = new Response(null, { status: 502 });
16
+ expect(config.shouldRetry(mockResponse, 1)).to.be.true;
17
+ });
18
+ it('should not retry on non-5xx status codes', async () => {
19
+ const config = new DefaultRetryConfiguration();
20
+ const mockResponse = new Response(null, { status: 404 });
21
+ expect(config.shouldRetry(mockResponse, 1)).to.be.false;
22
+ });
23
+ it('has exponential backoff delay', async () => {
24
+ const config = new DefaultRetryConfiguration();
25
+ expect(config.retryDelay(0)).to.equal(500);
26
+ expect(config.retryDelay(1)).to.equal(1000);
27
+ expect(config.retryDelay(2)).to.equal(2000);
28
+ });
29
+ });
30
+ //# sourceMappingURL=default-retry-config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"default-retry-config.test.js","sourceRoot":"","sources":["../../test/default-retry-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,yBAAyB,EAAE,MAAM,8DAA8D,CAAC;AAEzG,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,MAAM,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,MAAM,GAAG,IAAI,yBAAyB,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kCAAkC,EAAE,KAAK,IAAI,EAAE;QAChD,MAAM,MAAM,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,MAAM,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,MAAM,GAAG,IAAI,yBAAyB,EAAE,CAAC;QAC/C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { DefaultRetryConfiguration } from '../src/fetch-retry/configuration/default-retry-configuration';\n\ndescribe('DefaultRetryConfiguration', () => {\n it('should not retry on null response', async () => {\n const config = new DefaultRetryConfiguration();\n expect(config.shouldRetry(null, 1)).to.be.false;\n });\n\n it('should not retry after max retries exceeded', async () => {\n const config = new DefaultRetryConfiguration({ maxRetries: 2 });\n const mockResponse = new Response(null, { status: 500 });\n expect(config.shouldRetry(mockResponse, 3)).to.be.false;\n });\n\n it('should retry on 5xx status codes', async () => {\n const config = new DefaultRetryConfiguration();\n const mockResponse = new Response(null, { status: 502 });\n expect(config.shouldRetry(mockResponse, 1)).to.be.true;\n });\n\n it('should not retry on non-5xx status codes', async () => {\n const config = new DefaultRetryConfiguration();\n const mockResponse = new Response(null, { status: 404 });\n expect(config.shouldRetry(mockResponse, 1)).to.be.false;\n });\n\n it('has exponential backoff delay', async () => {\n const config = new DefaultRetryConfiguration();\n expect(config.retryDelay(0)).to.equal(500);\n expect(config.retryDelay(1)).to.equal(1000);\n expect(config.retryDelay(2)).to.equal(2000);\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,87 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { IaFetchHandler } from '../src/fetch-handler';
3
+ import { MockFetchRetrier } from './mocks/mock-fetch-retrier';
4
+ import { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';
5
+ describe('Fetch Handler', () => {
6
+ describe('fetch', () => {
7
+ it('adds reCache=1 if it is in the current url', async () => {
8
+ const fetchRetrier = new MockFetchRetrier();
9
+ const fetchHandler = new IaFetchHandler({
10
+ fetchRetrier: fetchRetrier,
11
+ searchParams: '?reCache=1',
12
+ });
13
+ await fetchHandler.fetch('https://foo.org/api/v1/snoot');
14
+ expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot?reCache=1');
15
+ });
16
+ it('appends reCache=1 when request is a Request object', async () => {
17
+ const fetchRetrier = new MockFetchRetrier();
18
+ const fetchHandler = new IaFetchHandler({
19
+ fetchRetrier,
20
+ searchParams: '?reCache=1',
21
+ });
22
+ const req = new Request('https://foo.org/api/v1/snoot');
23
+ await fetchHandler.fetch(req);
24
+ expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot?reCache=1');
25
+ });
26
+ it('does not append reCache when not present', async () => {
27
+ const fetchRetrier = new MockFetchRetrier();
28
+ const fetchHandler = new IaFetchHandler({
29
+ fetchRetrier,
30
+ searchParams: '?foo=bar',
31
+ });
32
+ await fetchHandler.fetch('https://foo.org/api/v1/snoot');
33
+ expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot');
34
+ });
35
+ });
36
+ describe('fetchIAApiResponse', () => {
37
+ it('prepends the IA basehost to the url when making a request', async () => {
38
+ const endpoint = '/foo/service/endpoint.php';
39
+ const fetchRetrier = new MockFetchRetrier();
40
+ const fetchHandler = new IaFetchHandler({
41
+ iaApiBaseUrl: 'www.example.com',
42
+ fetchRetrier: fetchRetrier,
43
+ });
44
+ await fetchHandler.fetchIAApiResponse(endpoint);
45
+ expect(fetchRetrier.requestInfo).to.equal('www.example.com/foo/service/endpoint.php');
46
+ });
47
+ });
48
+ describe('fetchApiResponse', () => {
49
+ it('adds credentials: include if requested', async () => {
50
+ const endpoint = '/foo/service/endpoint.php';
51
+ const fetchRetrier = new MockFetchRetrier();
52
+ const fetchHandler = new IaFetchHandler({
53
+ iaApiBaseUrl: 'www.example.com',
54
+ fetchRetrier: fetchRetrier,
55
+ });
56
+ await fetchHandler.fetchApiResponse(endpoint, {
57
+ includeCredentials: true,
58
+ });
59
+ expect(fetchRetrier.init).to.deep.equal({ credentials: 'include' });
60
+ });
61
+ it('passes method, body, and headers to RequestInit', async () => {
62
+ const fetchRetrier = new MockFetchRetrier();
63
+ const fetchHandler = new IaFetchHandler({ fetchRetrier });
64
+ const body = JSON.stringify({ hello: 'world' });
65
+ await fetchHandler.fetchApiResponse('https://example.org/api', {
66
+ method: 'POST',
67
+ body,
68
+ headers: { 'x-test': '1', 'content-type': 'application/json' },
69
+ });
70
+ expect(fetchRetrier.init).to.deep.equal({
71
+ method: 'POST',
72
+ body,
73
+ headers: { 'x-test': '1', 'content-type': 'application/json' },
74
+ });
75
+ });
76
+ it('passes retryConfig through to retrier', async () => {
77
+ const fetchRetrier = new MockFetchRetrier();
78
+ const retryConfig = new NoRetryConfiguration();
79
+ const fetchHandler = new IaFetchHandler({ fetchRetrier });
80
+ await fetchHandler.fetchApiResponse('https://example.org/api', {
81
+ retryConfig,
82
+ });
83
+ expect(fetchRetrier.retryConfig).to.equal(retryConfig);
84
+ });
85
+ });
86
+ });
87
+ //# sourceMappingURL=fetch-handler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-handler.test.js","sourceRoot":"","sources":["../../test/fetch-handler.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { IaFetchHandler } from '../src/fetch-handler';\nimport { MockFetchRetrier } from './mocks/mock-fetch-retrier';\nimport { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';\n\ndescribe('Fetch Handler', () => {\n describe('fetch', () => {\n it('adds reCache=1 if it is in the current url', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier: fetchRetrier,\n searchParams: '?reCache=1',\n });\n await fetchHandler.fetch('https://foo.org/api/v1/snoot');\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://foo.org/api/v1/snoot?reCache=1',\n );\n });\n\n it('appends reCache=1 when request is a Request object', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier,\n searchParams: '?reCache=1',\n });\n const req = new Request('https://foo.org/api/v1/snoot');\n await fetchHandler.fetch(req);\n expect(fetchRetrier.requestInfo).to.equal(\n 'https://foo.org/api/v1/snoot?reCache=1',\n );\n });\n\n it('does not append reCache when not present', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n fetchRetrier,\n searchParams: '?foo=bar',\n });\n await fetchHandler.fetch('https://foo.org/api/v1/snoot');\n expect(fetchRetrier.requestInfo).to.equal('https://foo.org/api/v1/snoot');\n });\n });\n\n describe('fetchIAApiResponse', () => {\n it('prepends the IA basehost to the url when making a request', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n iaApiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchIAApiResponse(endpoint);\n expect(fetchRetrier.requestInfo).to.equal(\n 'www.example.com/foo/service/endpoint.php',\n );\n });\n });\n\n describe('fetchApiResponse', () => {\n it('adds credentials: include if requested', async () => {\n const endpoint = '/foo/service/endpoint.php';\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({\n iaApiBaseUrl: 'www.example.com',\n fetchRetrier: fetchRetrier,\n });\n await fetchHandler.fetchApiResponse(endpoint, {\n includeCredentials: true,\n });\n expect(fetchRetrier.init).to.deep.equal({ credentials: 'include' });\n });\n\n it('passes method, body, and headers to RequestInit', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const fetchHandler = new IaFetchHandler({ fetchRetrier });\n const body = JSON.stringify({ hello: 'world' });\n await fetchHandler.fetchApiResponse('https://example.org/api', {\n method: 'POST',\n body,\n headers: { 'x-test': '1', 'content-type': 'application/json' },\n });\n expect(fetchRetrier.init).to.deep.equal({\n method: 'POST',\n body,\n headers: { 'x-test': '1', 'content-type': 'application/json' },\n });\n });\n\n it('passes retryConfig through to retrier', async () => {\n const fetchRetrier = new MockFetchRetrier();\n const retryConfig = new NoRetryConfiguration();\n const fetchHandler = new IaFetchHandler({ fetchRetrier });\n await fetchHandler.fetchApiResponse('https://example.org/api', {\n retryConfig,\n });\n expect(fetchRetrier.retryConfig).to.equal(retryConfig);\n });\n });\n});\n"]}
@@ -1,15 +1,14 @@
1
1
  import { expect } from '@open-wc/testing';
2
2
  import sinon from 'sinon';
3
- import { FetchRetrier } from '../src/utils/fetch-retrier';
3
+ import { FetchRetrier } from '../src/fetch-retry/fetch-retrier';
4
4
  import { MockAnalyticsHandler } from './mocks/mock-analytics-handler';
5
+ import { MockRetryConfig } from './mocks/mock-retry-config';
5
6
  describe('FetchRetrier', () => {
6
7
  let fetchStub;
7
- let sleepStub;
8
8
  let analytics;
9
9
  beforeEach(() => {
10
10
  analytics = new MockAnalyticsHandler();
11
11
  fetchStub = sinon.stub(globalThis, 'fetch');
12
- sleepStub = sinon.stub().resolves(); // stubbed promisedSleep
13
12
  });
14
13
  afterEach(() => {
15
14
  fetchStub.restore();
@@ -18,25 +17,45 @@ describe('FetchRetrier', () => {
18
17
  fetchStub.resolves(new Response('ok', { status: 200 }));
19
18
  const retrier = new FetchRetrier({
20
19
  analyticsHandler: analytics,
21
- sleepFn: sleepStub,
20
+ retryConfiguration: new MockRetryConfig(),
22
21
  });
23
22
  const res = await retrier.fetchRetry('https://foo.org/data');
24
23
  expect(res.status).to.equal(200);
25
24
  expect(fetchStub.callCount).to.equal(1);
26
- expect(sleepStub.callCount).to.equal(0);
27
25
  expect(analytics.events.length).to.equal(0);
28
26
  });
27
+ it('does not retry on 4xx and logs event', async () => {
28
+ fetchStub.resolves(new Response('forbidden', { status: 403 }));
29
+ const retrier = new FetchRetrier({
30
+ analyticsHandler: analytics,
31
+ });
32
+ const res = await retrier.fetchRetry('https://foo.org/403');
33
+ expect(res.status).to.equal(403);
34
+ expect(fetchStub.callCount).to.equal(1);
35
+ expect(analytics.events[0].action).to.equal('status4xxResponse');
36
+ });
29
37
  it('does not retry on 404 and logs event', async () => {
30
38
  fetchStub.resolves(new Response('not found', { status: 404 }));
31
39
  const retrier = new FetchRetrier({
32
40
  analyticsHandler: analytics,
33
- sleepFn: sleepStub,
34
41
  });
35
42
  const res = await retrier.fetchRetry('https://foo.org/404');
36
43
  expect(res.status).to.equal(404);
37
44
  expect(fetchStub.callCount).to.equal(1);
38
- expect(sleepStub.callCount).to.equal(0);
39
- expect(analytics.events[0].action).to.equal('status404NotRetrying');
45
+ expect(analytics.events[0].action).to.equal('status4xxResponse');
46
+ });
47
+ it('retries on 4xx if shouldRetry is true in ApiRequestInit', async () => {
48
+ fetchStub.onCall(0).resolves(new Response('bad request', { status: 400 }));
49
+ fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));
50
+ const retrier = new FetchRetrier({
51
+ analyticsHandler: analytics,
52
+ });
53
+ const res = await retrier.fetchRetry('https://foo.org/should-retry', {
54
+ retryConfig: new MockRetryConfig(),
55
+ });
56
+ expect(res.status).to.equal(200);
57
+ expect(fetchStub.callCount).to.equal(2);
58
+ expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;
40
59
  });
41
60
  it('retries on 500 and logs retry/failure events', async () => {
42
61
  fetchStub.onCall(0).resolves(new Response('fail', { status: 500 }));
@@ -44,14 +63,11 @@ describe('FetchRetrier', () => {
44
63
  fetchStub.onCall(2).resolves(new Response('still fail', { status: 500 }));
45
64
  const retrier = new FetchRetrier({
46
65
  analyticsHandler: analytics,
47
- retryCount: 2,
48
- retryDelay: 1,
49
- sleepFn: sleepStub,
66
+ retryConfiguration: new MockRetryConfig(),
50
67
  });
51
68
  const res = await retrier.fetchRetry('https://foo.org/fail');
52
69
  expect(res.status).to.equal(500);
53
70
  expect(fetchStub.callCount).to.equal(3);
54
- expect(sleepStub.callCount).to.equal(2);
55
71
  expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;
56
72
  expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;
57
73
  });
@@ -60,23 +76,18 @@ describe('FetchRetrier', () => {
60
76
  fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));
61
77
  const retrier = new FetchRetrier({
62
78
  analyticsHandler: analytics,
63
- retryCount: 1,
64
- retryDelay: 1,
65
- sleepFn: sleepStub,
79
+ retryConfiguration: new MockRetryConfig(),
66
80
  });
67
81
  const res = await retrier.fetchRetry('https://foo.org/retry');
68
82
  expect(res.status).to.equal(200);
69
83
  expect(fetchStub.callCount).to.equal(2);
70
- expect(sleepStub.calledOnce).to.be.true;
71
84
  expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;
72
85
  });
73
86
  it('throws and logs when retries are exhausted due to network error', async () => {
74
87
  fetchStub.rejects(new Error('Boom'));
75
88
  const retrier = new FetchRetrier({
76
89
  analyticsHandler: analytics,
77
- retryCount: 1,
78
- retryDelay: 1,
79
- sleepFn: sleepStub,
90
+ retryConfiguration: new MockRetryConfig(),
80
91
  });
81
92
  try {
82
93
  await retrier.fetchRetry('https://foo.org/networkfail');
@@ -85,8 +96,7 @@ describe('FetchRetrier', () => {
85
96
  catch (err) {
86
97
  expect(err.message).to.equal('Boom');
87
98
  }
88
- expect(fetchStub.callCount).to.equal(2);
89
- expect(sleepStub.callCount).to.equal(1);
99
+ expect(fetchStub.callCount).to.equal(3);
90
100
  expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;
91
101
  });
92
102
  it('detects content blocker error and does not retry', async () => {
@@ -94,8 +104,6 @@ describe('FetchRetrier', () => {
94
104
  fetchStub.rejects(blockerError);
95
105
  const retrier = new FetchRetrier({
96
106
  analyticsHandler: analytics,
97
- retryCount: 2,
98
- sleepFn: sleepStub,
99
107
  });
100
108
  try {
101
109
  await retrier.fetchRetry('https://foo.org/blocked');
@@ -105,35 +113,61 @@ describe('FetchRetrier', () => {
105
113
  expect(err).to.equal(blockerError);
106
114
  }
107
115
  expect(fetchStub.callCount).to.equal(1);
108
- expect(sleepStub.callCount).to.equal(0);
109
116
  expect(analytics.events.some(e => e.action === 'contentBlockerDetectedNotRetrying')).to.be.true;
110
117
  });
111
- it('calls sleepFn on retry with correct delay', async () => {
112
- fetchStub.onCall(0).resolves(new Response(null, { status: 500 }));
113
- fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));
118
+ it('sleeps for each retry attempt', async () => {
119
+ const retryConfig = new MockRetryConfig();
120
+ const retryDelaySpy = sinon.spy(retryConfig, 'retryDelay');
121
+ fetchStub.resolves(new Response(null, { status: 500 }));
114
122
  const retrier = new FetchRetrier({
115
123
  analyticsHandler: analytics,
116
- retryCount: 2,
117
- retryDelay: 1234,
118
- sleepFn: sleepStub,
124
+ retryConfiguration: retryConfig,
119
125
  });
120
- const res = await retrier.fetchRetry('https://foo.org/retry-with-sleep');
121
- expect(res.status).to.equal(200);
122
- expect(sleepStub.calledOnce).to.be.true;
123
- expect(sleepStub.calledWith(1234)).to.be.true;
126
+ const res = await retrier.fetchRetry('https://foo.org/retry-fail');
127
+ expect(res.status).to.equal(500);
128
+ expect(fetchStub.callCount).to.equal(3);
129
+ expect(retryDelaySpy.callCount).to.equal(2);
124
130
  });
125
- it('sleeps for each retry attempt', async () => {
126
- fetchStub.resolves(new Response(null, { status: 500 }));
131
+ it('does not retry 5xx when NoRetryConfiguration is used', async () => {
132
+ fetchStub.resolves(new Response('server error', { status: 500 }));
127
133
  const retrier = new FetchRetrier({
128
134
  analyticsHandler: analytics,
129
- retryCount: 2,
130
- retryDelay: 300,
131
- sleepFn: sleepStub,
135
+ retryConfiguration: new (class {
136
+ shouldRetry() {
137
+ return false;
138
+ }
139
+ retryDelay() {
140
+ return 0;
141
+ }
142
+ })(),
132
143
  });
133
- const res = await retrier.fetchRetry('https://foo.org/retry-fail');
144
+ const res = await retrier.fetchRetry('https://foo.org/no-retry-500');
134
145
  expect(res.status).to.equal(500);
135
- expect(sleepStub.callCount).to.equal(2);
136
- expect(sleepStub.alwaysCalledWith(300)).to.be.true;
146
+ expect(fetchStub.callCount).to.equal(1);
147
+ expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;
148
+ });
149
+ it('does not retry on error when configuration disables retries', async () => {
150
+ fetchStub.rejects(new Error('Immediate failure'));
151
+ const retrier = new FetchRetrier({
152
+ analyticsHandler: analytics,
153
+ retryConfiguration: new (class {
154
+ shouldRetry() {
155
+ return false;
156
+ }
157
+ retryDelay() {
158
+ return 0;
159
+ }
160
+ })(),
161
+ });
162
+ try {
163
+ await retrier.fetchRetry('https://foo.org/no-retry-error');
164
+ throw new Error('Should have thrown');
165
+ }
166
+ catch (err) {
167
+ expect(err.message).to.equal('Immediate failure');
168
+ }
169
+ expect(fetchStub.callCount).to.equal(1);
170
+ expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;
137
171
  });
138
172
  });
139
173
  //# sourceMappingURL=fetch-retrier.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-retrier.test.js","sourceRoot":"","sources":["../../test/fetch-retrier.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport sinon from 'sinon';\nimport { FetchRetrier } from '../src/utils/fetch-retrier';\nimport { MockAnalyticsHandler } from './mocks/mock-analytics-handler';\n\ndescribe('FetchRetrier', () => {\n let fetchStub: sinon.SinonStub;\n let sleepStub: sinon.SinonStub;\n let analytics: MockAnalyticsHandler;\n\n beforeEach(() => {\n analytics = new MockAnalyticsHandler();\n fetchStub = sinon.stub(globalThis, 'fetch');\n sleepStub = sinon.stub().resolves(); // stubbed promisedSleep\n });\n\n afterEach(() => {\n fetchStub.restore();\n });\n\n it('returns response on first success', async () => {\n fetchStub.resolves(new Response('ok', { status: 200 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n sleepFn: sleepStub,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/data');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(1);\n expect(sleepStub.callCount).to.equal(0);\n expect(analytics.events.length).to.equal(0);\n });\n\n it('does not retry on 404 and logs event', async () => {\n fetchStub.resolves(new Response('not found', { status: 404 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n sleepFn: sleepStub,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/404');\n\n expect(res.status).to.equal(404);\n expect(fetchStub.callCount).to.equal(1);\n expect(sleepStub.callCount).to.equal(0);\n expect(analytics.events[0].action).to.equal('status404NotRetrying');\n });\n\n it('retries on 500 and logs retry/failure events', async () => {\n fetchStub.onCall(0).resolves(new Response('fail', { status: 500 }));\n fetchStub.onCall(1).resolves(new Response('fail again', { status: 500 }));\n fetchStub.onCall(2).resolves(new Response('still fail', { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryCount: 2,\n retryDelay: 1,\n sleepFn: sleepStub,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(sleepStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('retries on fetch error and eventually succeeds', async () => {\n fetchStub.onCall(0).rejects(new Error('Network error'));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryCount: 1,\n retryDelay: 1,\n sleepFn: sleepStub,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(sleepStub.calledOnce).to.be.true;\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('throws and logs when retries are exhausted due to network error', async () => {\n fetchStub.rejects(new Error('Boom'));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryCount: 1,\n retryDelay: 1,\n sleepFn: sleepStub,\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/networkfail');\n throw new Error('Should have thrown');\n } catch (err: any) {\n expect(err.message).to.equal('Boom');\n }\n\n expect(fetchStub.callCount).to.equal(2);\n expect(sleepStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('detects content blocker error and does not retry', async () => {\n const blockerError = new TypeError('Content Blocker denied request');\n fetchStub.rejects(blockerError);\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryCount: 2,\n sleepFn: sleepStub,\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/blocked');\n throw new Error('Should have thrown');\n } catch (err: any) {\n expect(err).to.equal(blockerError);\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(sleepStub.callCount).to.equal(0);\n expect(\n analytics.events.some(\n e => e.action === 'contentBlockerDetectedNotRetrying',\n ),\n ).to.be.true;\n });\n\n it('calls sleepFn on retry with correct delay', async () => {\n fetchStub.onCall(0).resolves(new Response(null, { status: 500 }));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryCount: 2,\n retryDelay: 1234,\n sleepFn: sleepStub,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry-with-sleep');\n\n expect(res.status).to.equal(200);\n expect(sleepStub.calledOnce).to.be.true;\n expect(sleepStub.calledWith(1234)).to.be.true;\n });\n\n it('sleeps for each retry attempt', async () => {\n fetchStub.resolves(new Response(null, { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryCount: 2,\n retryDelay: 300,\n sleepFn: sleepStub,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry-fail');\n\n expect(res.status).to.equal(500);\n expect(sleepStub.callCount).to.equal(2);\n expect(sleepStub.alwaysCalledWith(300)).to.be.true;\n });\n});\n"]}
1
+ {"version":3,"file":"fetch-retrier.test.js","sourceRoot":"","sources":["../../test/fetch-retrier.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from '@open-wc/testing';\nimport sinon from 'sinon';\nimport { FetchRetrier } from '../src/fetch-retry/fetch-retrier';\nimport { MockAnalyticsHandler } from './mocks/mock-analytics-handler';\nimport { MockRetryConfig } from './mocks/mock-retry-config';\n\ndescribe('FetchRetrier', () => {\n let fetchStub: sinon.SinonStub;\n let analytics: MockAnalyticsHandler;\n\n beforeEach(() => {\n analytics = new MockAnalyticsHandler();\n fetchStub = sinon.stub(globalThis, 'fetch');\n });\n\n afterEach(() => {\n fetchStub.restore();\n });\n\n it('returns response on first success', async () => {\n fetchStub.resolves(new Response('ok', { status: 200 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/data');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.length).to.equal(0);\n });\n\n it('does not retry on 4xx and logs event', async () => {\n fetchStub.resolves(new Response('forbidden', { status: 403 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/403');\n\n expect(res.status).to.equal(403);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events[0].action).to.equal('status4xxResponse');\n });\n\n it('does not retry on 404 and logs event', async () => {\n fetchStub.resolves(new Response('not found', { status: 404 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/404');\n\n expect(res.status).to.equal(404);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events[0].action).to.equal('status4xxResponse');\n });\n\n it('retries on 4xx if shouldRetry is true in ApiRequestInit', async () => {\n fetchStub.onCall(0).resolves(new Response('bad request', { status: 400 }));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/should-retry', {\n retryConfig: new MockRetryConfig(),\n });\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('retries on 500 and logs retry/failure events', async () => {\n fetchStub.onCall(0).resolves(new Response('fail', { status: 500 }));\n fetchStub.onCall(1).resolves(new Response('fail again', { status: 500 }));\n fetchStub.onCall(2).resolves(new Response('still fail', { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('retries on fetch error and eventually succeeds', async () => {\n fetchStub.onCall(0).rejects(new Error('Network error'));\n fetchStub.onCall(1).resolves(new Response('ok', { status: 200 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry');\n\n expect(res.status).to.equal(200);\n expect(fetchStub.callCount).to.equal(2);\n expect(analytics.events.some(e => e.action === 'retryingFetch')).to.be.true;\n });\n\n it('throws and logs when retries are exhausted due to network error', async () => {\n fetchStub.rejects(new Error('Boom'));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new MockRetryConfig(),\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/networkfail');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect((err as Error).message).to.equal('Boom');\n }\n\n expect(fetchStub.callCount).to.equal(3);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('detects content blocker error and does not retry', async () => {\n const blockerError = new TypeError('Content Blocker denied request');\n fetchStub.rejects(blockerError);\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/blocked');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect(err).to.equal(blockerError);\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(\n analytics.events.some(\n e => e.action === 'contentBlockerDetectedNotRetrying',\n ),\n ).to.be.true;\n });\n\n it('sleeps for each retry attempt', async () => {\n const retryConfig = new MockRetryConfig();\n const retryDelaySpy = sinon.spy(retryConfig, 'retryDelay');\n fetchStub.resolves(new Response(null, { status: 500 }));\n\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: retryConfig,\n });\n\n const res = await retrier.fetchRetry('https://foo.org/retry-fail');\n\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(3);\n expect(retryDelaySpy.callCount).to.equal(2);\n });\n\n it('does not retry 5xx when NoRetryConfiguration is used', async () => {\n fetchStub.resolves(new Response('server error', { status: 500 }));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new (class {\n shouldRetry() {\n return false;\n }\n retryDelay() {\n return 0;\n }\n })(),\n });\n\n const res = await retrier.fetchRetry('https://foo.org/no-retry-500');\n expect(res.status).to.equal(500);\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n\n it('does not retry on error when configuration disables retries', async () => {\n fetchStub.rejects(new Error('Immediate failure'));\n const retrier = new FetchRetrier({\n analyticsHandler: analytics,\n retryConfiguration: new (class {\n shouldRetry() {\n return false;\n }\n retryDelay() {\n return 0;\n }\n })(),\n });\n\n try {\n await retrier.fetchRetry('https://foo.org/no-retry-error');\n throw new Error('Should have thrown');\n } catch (err: unknown) {\n expect((err as Error).message).to.equal('Immediate failure');\n }\n\n expect(fetchStub.callCount).to.equal(1);\n expect(analytics.events.some(e => e.action === 'fetchFailed')).to.be.true;\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';
3
+ describe('legacyArgsAsFetchOptions', () => {
4
+ it('wraps RequestInit into FetchOptions', () => {
5
+ const init = { method: 'PUT' };
6
+ const fo = legacyArgsAsFetchOptions(init);
7
+ expect(fo).to.deep.equal({ requestInit: init });
8
+ });
9
+ it('returns FetchOptions unchanged', () => {
10
+ const options = {
11
+ requestInit: { headers: { foo: 'bar' } },
12
+ };
13
+ const fo = legacyArgsAsFetchOptions(options);
14
+ expect(fo).to.equal(options);
15
+ });
16
+ it('returns undefined when no options provided', () => {
17
+ const fo = legacyArgsAsFetchOptions(undefined);
18
+ expect(fo).to.equal(undefined);
19
+ });
20
+ });
21
+ //# sourceMappingURL=legacy-args.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-args.test.js","sourceRoot":"","sources":["../../test/legacy-args.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAG1E,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,IAAI,GAAgB,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;QAC5C,MAAM,EAAE,GAAG,wBAAwB,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QACxC,MAAM,OAAO,GAAiB;YAC5B,WAAW,EAAE,EAAE,OAAO,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;SACzC,CAAC;QACF,MAAM,EAAE,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,EAAE,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';\nimport type { FetchOptions } from '../src/fetch-options';\n\ndescribe('legacyArgsAsFetchOptions', () => {\n it('wraps RequestInit into FetchOptions', () => {\n const init: RequestInit = { method: 'PUT' };\n const fo = legacyArgsAsFetchOptions(init);\n expect(fo).to.deep.equal({ requestInit: init });\n });\n\n it('returns FetchOptions unchanged', () => {\n const options: FetchOptions = {\n requestInit: { headers: { foo: 'bar' } },\n };\n const fo = legacyArgsAsFetchOptions(options);\n expect(fo).to.equal(options);\n });\n\n it('returns undefined when no options provided', () => {\n const fo = legacyArgsAsFetchOptions(undefined);\n expect(fo).to.equal(undefined);\n });\n});\n"]}
@@ -0,0 +1,10 @@
1
+ import type { FetchOptions } from '../../src/fetch-options';
2
+ import type { FetchRetrierInterface } from '../../src/fetch-retry/fetch-retrier';
3
+ import type { RetryConfiguring } from '../../src/fetch-retry/configuration/retry-configuring';
4
+ export declare class MockFetchRetrier implements FetchRetrierInterface {
5
+ requestInfo?: RequestInfo;
6
+ init?: RequestInit;
7
+ retries?: number;
8
+ retryConfig?: RetryConfiguring;
9
+ fetchRetry(request: RequestInfo, options?: RequestInit | FetchOptions): Promise<Response>;
10
+ }
@@ -0,0 +1,11 @@
1
+ import { legacyArgsAsFetchOptions } from '../../src/fetch-retry/legacy-args';
2
+ export class MockFetchRetrier {
3
+ async fetchRetry(request, options) {
4
+ const fetchOptions = legacyArgsAsFetchOptions(options);
5
+ this.init = fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.requestInit;
6
+ this.retryConfig = fetchOptions === null || fetchOptions === void 0 ? void 0 : fetchOptions.retryConfig;
7
+ this.requestInfo = request;
8
+ return new Response(JSON.stringify({ boop: 'snoot' }), { status: 200 });
9
+ }
10
+ }
11
+ //# sourceMappingURL=mock-fetch-retrier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-fetch-retrier.js","sourceRoot":"","sources":["../../../test/mocks/mock-fetch-retrier.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mCAAmC,CAAC;AAE7E,MAAM,OAAO,gBAAgB;IAM3B,KAAK,CAAC,UAAU,CACd,OAAoB,EACpB,OAAoC;QAEpC,MAAM,YAAY,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;QACvD,IAAI,CAAC,IAAI,GAAG,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,WAAW,CAAC;QACtC,IAAI,CAAC,WAAW,GAAG,YAAY,aAAZ,YAAY,uBAAZ,YAAY,CAAE,WAAW,CAAC;QAC7C,IAAI,CAAC,WAAW,GAAG,OAAO,CAAC;QAC3B,OAAO,IAAI,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAC1E,CAAC;CACF","sourcesContent":["import type { FetchOptions } from '../../src/fetch-options';\nimport type { FetchRetrierInterface } from '../../src/fetch-retry/fetch-retrier';\nimport type { RetryConfiguring } from '../../src/fetch-retry/configuration/retry-configuring';\nimport { legacyArgsAsFetchOptions } from '../../src/fetch-retry/legacy-args';\n\nexport class MockFetchRetrier implements FetchRetrierInterface {\n requestInfo?: RequestInfo;\n init?: RequestInit;\n retries?: number;\n retryConfig?: RetryConfiguring;\n\n async fetchRetry(\n request: RequestInfo,\n options?: RequestInit | FetchOptions,\n ): Promise<Response> {\n const fetchOptions = legacyArgsAsFetchOptions(options);\n this.init = fetchOptions?.requestInit;\n this.retryConfig = fetchOptions?.retryConfig;\n this.requestInfo = request;\n return new Response(JSON.stringify({ boop: 'snoot' }), { status: 200 });\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { RetryConfiguring } from '../../src/fetch-retry/configuration/retry-configuring';
2
+ export declare class MockRetryConfig implements RetryConfiguring {
3
+ mockRetryCount: number;
4
+ mockRetryDelay: number;
5
+ shouldRetry(response: Response | null, retryNumber: number, error?: unknown): boolean;
6
+ retryDelay(): number;
7
+ }
@@ -0,0 +1,13 @@
1
+ export class MockRetryConfig {
2
+ constructor() {
3
+ this.mockRetryCount = 2;
4
+ this.mockRetryDelay = 0;
5
+ }
6
+ shouldRetry(response, retryNumber, error) {
7
+ return retryNumber < this.mockRetryCount;
8
+ }
9
+ retryDelay() {
10
+ return this.mockRetryDelay;
11
+ }
12
+ }
13
+ //# sourceMappingURL=mock-retry-config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mock-retry-config.js","sourceRoot":"","sources":["../../../test/mocks/mock-retry-config.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,eAAe;IAA5B;QACE,mBAAc,GAAW,CAAC,CAAC;QAE3B,mBAAc,GAAW,CAAC,CAAC;IAa7B,CAAC;IAXC,WAAW,CACT,QAAyB,EACzB,WAAmB,EACnB,KAAe;QAEf,OAAO,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC;IAC3C,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;CACF","sourcesContent":["import type { RetryConfiguring } from '../../src/fetch-retry/configuration/retry-configuring';\n\nexport class MockRetryConfig implements RetryConfiguring {\n mockRetryCount: number = 2;\n\n mockRetryDelay: number = 0;\n\n shouldRetry(\n response: Response | null,\n retryNumber: number,\n error?: unknown,\n ): boolean {\n return retryNumber < this.mockRetryCount;\n }\n\n retryDelay(): number {\n return this.mockRetryDelay;\n }\n}\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';
3
+ describe('NoRetryConfiguration', () => {
4
+ it('should not retry', async () => {
5
+ const config = new NoRetryConfiguration();
6
+ expect(config.shouldRetry()).to.be.false;
7
+ });
8
+ it('has no delay', async () => {
9
+ const config = new NoRetryConfiguration();
10
+ expect(config.retryDelay()).to.equal(0);
11
+ });
12
+ });
13
+ //# sourceMappingURL=no-retry-config.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-retry-config.test.js","sourceRoot":"","sources":["../../test/no-retry-config.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,oBAAoB,EAAE,MAAM,yDAAyD,CAAC;AAE/F,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,kBAAkB,EAAE,KAAK,IAAI,EAAE;QAChC,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,cAAc,EAAE,KAAK,IAAI,EAAE;QAC5B,MAAM,MAAM,GAAG,IAAI,oBAAoB,EAAE,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { NoRetryConfiguration } from '../src/fetch-retry/configuration/no-retry-configuration';\n\ndescribe('NoRetryConfiguration', () => {\n it('should not retry', async () => {\n const config = new NoRetryConfiguration();\n expect(config.shouldRetry()).to.be.false;\n });\n\n it('has no delay', async () => {\n const config = new NoRetryConfiguration();\n expect(config.retryDelay()).to.equal(0);\n });\n});\n"]}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,27 @@
1
+ import { expect } from '@open-wc/testing';
2
+ import { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';
3
+ import { MockRetryConfig } from './mocks/mock-retry-config';
4
+ describe('FetchRetrier Legacy Args', () => {
5
+ it('can convert RequestInit to FetchOptions', async () => {
6
+ const options = legacyArgsAsFetchOptions({ method: 'GET' });
7
+ expect(options).to.deep.equal({
8
+ requestInit: {
9
+ method: 'GET',
10
+ },
11
+ });
12
+ });
13
+ it('leaves FetchOptions unchanged', async () => {
14
+ const retryConfig = new MockRetryConfig();
15
+ const options = legacyArgsAsFetchOptions({
16
+ requestInit: { method: 'POST' },
17
+ retryConfig: retryConfig,
18
+ });
19
+ expect(options).to.deep.equal({
20
+ requestInit: {
21
+ method: 'POST',
22
+ },
23
+ retryConfig: retryConfig,
24
+ });
25
+ });
26
+ });
27
+ //# sourceMappingURL=retrier-legacy-args.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retrier-legacy-args.test.js","sourceRoot":"","sources":["../../test/retrier-legacy-args.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAC1E,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE5D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,yCAAyC,EAAE,KAAK,IAAI,EAAE;QACvD,MAAM,OAAO,GAAG,wBAAwB,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YAC5B,WAAW,EAAE;gBACX,MAAM,EAAE,KAAK;aACd;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAI,EAAE;QAC7C,MAAM,WAAW,GAAG,IAAI,eAAe,EAAE,CAAC;QAC1C,MAAM,OAAO,GAAG,wBAAwB,CAAC;YACvC,WAAW,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;YAC/B,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;QACH,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YAC5B,WAAW,EAAE;gBACX,MAAM,EAAE,MAAM;aACf;YACD,WAAW,EAAE,WAAW;SACzB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["import { expect } from '@open-wc/testing';\nimport { legacyArgsAsFetchOptions } from '../src/fetch-retry/legacy-args';\nimport { MockRetryConfig } from './mocks/mock-retry-config';\n\ndescribe('FetchRetrier Legacy Args', () => {\n it('can convert RequestInit to FetchOptions', async () => {\n const options = legacyArgsAsFetchOptions({ method: 'GET' });\n expect(options).to.deep.equal({\n requestInit: {\n method: 'GET',\n },\n });\n });\n\n it('leaves FetchOptions unchanged', async () => {\n const retryConfig = new MockRetryConfig();\n const options = legacyArgsAsFetchOptions({\n requestInit: { method: 'POST' },\n retryConfig: retryConfig,\n });\n expect(options).to.deep.equal({\n requestInit: {\n method: 'POST',\n },\n retryConfig: retryConfig,\n });\n });\n});\n"]}
package/index.ts CHANGED
@@ -1,2 +1,10 @@
1
- export { IaFetchHandler } from './src/ia-fetch-handler';
1
+ export { IaFetchHandler } from './src/fetch-handler';
2
2
  export { FetchHandlerInterface } from './src/fetch-handler-interface';
3
+ export {
4
+ FetchRetrier,
5
+ FetchRetrierInterface,
6
+ } from './src/fetch-retry/fetch-retrier';
7
+ export { DefaultRetryConfiguration } from './src/fetch-retry/configuration/default-retry-configuration';
8
+ export { NoRetryConfiguration } from './src/fetch-retry/configuration/no-retry-configuration';
9
+ export type { RetryConfiguring } from './src/fetch-retry/configuration/retry-configuring';
10
+ export type { FetchOptions } from './src/fetch-options';