|
| 1 | +import { R2Conditional } from "@cloudflare/workers-types/experimental"; |
| 2 | +import { R2ObjectMetadata, _testR2Conditional } from "@miniflare/tre"; |
| 3 | +import test from "ava"; |
| 4 | + |
| 5 | +test("testR2Conditional: matches various conditions", (t) => { |
| 6 | + // Adapted from internal R2 gateway tests |
| 7 | + const etag = "test"; |
| 8 | + const badEtag = "not-test"; |
| 9 | + |
| 10 | + const uploadedDate = new Date("2023-02-24T00:09:00.500Z"); |
| 11 | + const pastDate = new Date(uploadedDate.getTime() - 30_000); |
| 12 | + const futureDate = new Date(uploadedDate.getTime() + 30_000); |
| 13 | + |
| 14 | + const metadata: Pick<R2ObjectMetadata, "etag" | "uploaded"> = { |
| 15 | + etag, |
| 16 | + uploaded: uploadedDate.getTime(), |
| 17 | + }; |
| 18 | + |
| 19 | + const using = (cond: R2Conditional) => _testR2Conditional(cond, metadata); |
| 20 | + const usingMissing = (cond: R2Conditional) => _testR2Conditional(cond); |
| 21 | + |
| 22 | + // Check single conditions |
| 23 | + t.true(using({ etagMatches: etag })); |
| 24 | + t.false(using({ etagMatches: badEtag })); |
| 25 | + |
| 26 | + t.true(using({ etagDoesNotMatch: badEtag })); |
| 27 | + t.false(using({ etagDoesNotMatch: etag })); |
| 28 | + |
| 29 | + t.false(using({ uploadedBefore: pastDate })); |
| 30 | + t.true(using({ uploadedBefore: futureDate })); |
| 31 | + |
| 32 | + t.true(using({ uploadedAfter: pastDate })); |
| 33 | + t.false(using({ uploadedBefore: pastDate })); |
| 34 | + |
| 35 | + // Check multiple conditions that evaluate to false |
| 36 | + t.false(using({ etagMatches: etag, etagDoesNotMatch: etag })); |
| 37 | + t.false(using({ etagMatches: etag, uploadedAfter: futureDate })); |
| 38 | + t.false( |
| 39 | + using({ |
| 40 | + // `etagMatches` pass makes `uploadedBefore` pass, but `uploadedAfter` fails |
| 41 | + etagMatches: etag, |
| 42 | + uploadedAfter: futureDate, |
| 43 | + uploadedBefore: pastDate, |
| 44 | + }) |
| 45 | + ); |
| 46 | + t.false(using({ etagDoesNotMatch: badEtag, uploadedBefore: pastDate })); |
| 47 | + t.false( |
| 48 | + using({ |
| 49 | + // `etagDoesNotMatch` pass makes `uploadedAfter` pass, but `uploadedBefore` fails |
| 50 | + etagDoesNotMatch: badEtag, |
| 51 | + uploadedAfter: futureDate, |
| 52 | + uploadedBefore: pastDate, |
| 53 | + }) |
| 54 | + ); |
| 55 | + t.false( |
| 56 | + using({ |
| 57 | + etagMatches: badEtag, |
| 58 | + etagDoesNotMatch: badEtag, |
| 59 | + uploadedAfter: pastDate, |
| 60 | + uploadedBefore: futureDate, |
| 61 | + }) |
| 62 | + ); |
| 63 | + |
| 64 | + // Check multiple conditions that evaluate to true |
| 65 | + t.true(using({ etagMatches: etag, etagDoesNotMatch: badEtag })); |
| 66 | + // `etagMatches` pass makes `uploadedBefore` pass |
| 67 | + t.true(using({ etagMatches: etag, uploadedBefore: pastDate })); |
| 68 | + // `etagDoesNotMatch` pass makes `uploadedAfter` pass |
| 69 | + t.true(using({ etagDoesNotMatch: badEtag, uploadedAfter: futureDate })); |
| 70 | + t.true( |
| 71 | + using({ |
| 72 | + // `etagMatches` pass makes `uploadedBefore` pass |
| 73 | + etagMatches: etag, |
| 74 | + uploadedBefore: pastDate, |
| 75 | + // `etagDoesNotMatch` pass makes `uploadedAfter` pass |
| 76 | + etagDoesNotMatch: badEtag, |
| 77 | + uploadedAfter: futureDate, |
| 78 | + }) |
| 79 | + ); |
| 80 | + t.true( |
| 81 | + using({ |
| 82 | + uploadedBefore: futureDate, |
| 83 | + // `etagDoesNotMatch` pass makes `uploadedAfter` pass |
| 84 | + etagDoesNotMatch: badEtag, |
| 85 | + uploadedAfter: futureDate, |
| 86 | + }) |
| 87 | + ); |
| 88 | + t.true( |
| 89 | + using({ |
| 90 | + uploadedAfter: pastDate, |
| 91 | + // `etagMatches` pass makes `uploadedBefore` pass |
| 92 | + etagMatches: etag, |
| 93 | + uploadedBefore: pastDate, |
| 94 | + }) |
| 95 | + ); |
| 96 | + |
| 97 | + // Check missing metadata fails with either `etagMatches` and `uploadedAfter` |
| 98 | + t.false(usingMissing({ etagMatches: etag })); |
| 99 | + t.false(usingMissing({ uploadedAfter: pastDate })); |
| 100 | + t.false(usingMissing({ etagMatches: etag, uploadedAfter: pastDate })); |
| 101 | + t.true(usingMissing({ etagDoesNotMatch: etag })); |
| 102 | + t.true(usingMissing({ uploadedBefore: pastDate })); |
| 103 | + t.true(usingMissing({ etagDoesNotMatch: etag, uploadedBefore: pastDate })); |
| 104 | + t.false(usingMissing({ etagMatches: etag, uploadedBefore: pastDate })); |
| 105 | + t.false(usingMissing({ etagDoesNotMatch: etag, uploadedAfter: pastDate })); |
| 106 | + |
| 107 | + // Check with second granularity |
| 108 | + const justPastDate = new Date(uploadedDate.getTime() - 250); |
| 109 | + const justFutureDate = new Date(uploadedDate.getTime() + 250); |
| 110 | + t.true(using({ uploadedAfter: justPastDate })); |
| 111 | + t.false(using({ uploadedAfter: justPastDate, secondsGranularity: true })); |
| 112 | + t.true(using({ uploadedBefore: justFutureDate })); |
| 113 | + t.false(using({ uploadedBefore: justFutureDate, secondsGranularity: true })); |
| 114 | +}); |
0 commit comments