@@ -60,6 +60,28 @@ function mockBucketLockPutWithExistingRules(
6060 ) ;
6161}
6262
63+ function mockBucketLockGetExistingRules (
64+ bucketName : string ,
65+ existingRules : BucketLockRule [ ]
66+ ) {
67+ msw . use (
68+ http . get (
69+ "*/accounts/:accountId/r2/buckets/:bucketName/lock" ,
70+ async ( { params } ) => {
71+ const { accountId, bucketName : bucketParam } = params ;
72+ expect ( accountId ) . toEqual ( "some-account-id" ) ;
73+ expect ( bucketParam ) . toEqual ( bucketName ) ;
74+ return HttpResponse . json (
75+ createFetchResult ( {
76+ rules : existingRules ,
77+ } )
78+ ) ;
79+ } ,
80+ { once : true }
81+ )
82+ ) ;
83+ }
84+
6385describe ( "r2" , ( ) => {
6486 const std = mockConsoleMethods ( ) ;
6587 beforeEach ( ( ) => msw . use ( ...mswR2handlers ) ) ;
@@ -2469,18 +2491,15 @@ describe("r2", () => {
24692491 } ) ;
24702492 describe ( "add" , ( ) => {
24712493 it ( "it should add a lock rule without prefix using command-line arguments" , async ( ) => {
2472- setIsTTY ( false ) ;
2494+ setIsTTY ( true ) ;
24732495 const bucketName = "my-bucket" ;
2474- const ruleId = "rule-no-prefix" ;
2475- const conditionTypeAge = "Age" ;
2476- const conditionValueAge = 1 ;
24772496
24782497 mockBucketLockPutNew ( bucketName , [
24792498 {
2480- id : ruleId ,
2499+ id : "rule-no-prefix" ,
24812500 enabled : true ,
24822501 condition : {
2483- type : conditionTypeAge ,
2502+ type : "Age" ,
24842503 maxAgeSeconds : 86400 ,
24852504 } ,
24862505 } ,
@@ -2493,159 +2512,162 @@ describe("r2", () => {
24932512 } ) ;
24942513 mockConfirm ( {
24952514 text :
2496- `Are you sure you want to add lock rule '${ ruleId } ' to bucket '${ bucketName } ' without a prefix? ` +
2515+ `Are you sure you want to add lock rule 'rule-no-prefix ' to bucket '${ bucketName } ' without a prefix? ` +
24972516 `The lock rule will apply to all objects in your bucket.` ,
24982517 result : true ,
24992518 } ) ;
25002519 await runWrangler (
2501- `r2 bucket lock add ${ bucketName } --id ${ ruleId } --lock-days ${ conditionValueAge } `
2520+ `r2 bucket lock add ${ bucketName } --id "rule-no-prefix" --lock-days 1 `
25022521 ) ;
25032522 expect ( std . out ) . toMatchInlineSnapshot ( `
2504- "? Enter a prefix for the bucket lock rule (set to \\"\\" for all prefixes)
2505- 🤖 Using default value in non-interactive context:
2506- Adding lock rule 'rule-no-prefix' to bucket 'my-bucket'...
2523+ "Adding lock rule 'rule-no-prefix' to bucket 'my-bucket'...
25072524 ✨ Added lock rule 'rule-no-prefix' to bucket 'my-bucket'."
25082525 ` ) ;
25092526 } ) ;
2527+ it ( "it should fail to add lock rule using command-line arguments without condition" , async ( ) => {
2528+ setIsTTY ( true ) ;
2529+ const bucketName = "my-bucket" ;
2530+
2531+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
2532+
2533+ mockConfirm ( {
2534+ text :
2535+ `Are you sure you want to add lock rule 'rule-not-indefinite' to bucket '${ bucketName } ' without an expiration? ` +
2536+ `The lock rule will apply to all matching objects indefinitely.` ,
2537+ result : false ,
2538+ } ) ;
2539+
2540+ await runWrangler (
2541+ `r2 bucket lock add ${ bucketName } --id 'rule-not-indefinite' --prefix prefix-not-indefinite`
2542+ ) ;
2543+ expect ( std . out ) . toMatchInlineSnapshot ( `
2544+ "Add cancelled."
2545+ ` ) ;
2546+ } ) ;
25102547 it ( "it should add an age lock rule using command-line arguments" , async ( ) => {
25112548 setIsTTY ( true ) ;
25122549 const bucketName = "my-bucket" ;
2513- const ruleIdAge = "rule-age" ;
2514- const prefixAge = "prefix-age" ;
2515- const conditionTypeAge = "Age" ;
2516- const conditionValueAge = 1 ;
25172550
25182551 mockBucketLockPutNew ( bucketName , [
25192552 {
2520- id : ruleIdAge ,
2553+ id : "rule-age" ,
25212554 enabled : true ,
2522- prefix : prefixAge ,
2555+ prefix : "prefix-age" ,
25232556 condition : {
2524- type : conditionTypeAge ,
2557+ type : "Age" ,
25252558 maxAgeSeconds : 86400 ,
25262559 } ,
25272560 } ,
25282561 ] ) ;
25292562 // age
25302563 await runWrangler (
2531- `r2 bucket lock add ${ bucketName } --id ${ ruleIdAge } --prefix ${ prefixAge } --lock-days ${ conditionValueAge } `
2564+ `r2 bucket lock add ${ bucketName } --id rule-age --prefix prefix-age --lock-days 1 `
25322565 ) ;
25332566 expect ( std . out ) . toMatchInlineSnapshot ( `
25342567 "Adding lock rule 'rule-age' to bucket 'my-bucket'...
25352568 ✨ Added lock rule 'rule-age' to bucket 'my-bucket'."
25362569 ` ) ;
25372570 } ) ;
2538- it ( "it should fail an age lock rule using command-line arguments with invalid age" , async ( ) => {
2571+ it ( "it should fail an age lock rule using command-line arguments with invalid age string" , async ( ) => {
2572+ setIsTTY ( true ) ;
2573+ const bucketName = "my-bucket" ;
2574+
2575+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
2576+ // age
2577+ await expect ( ( ) =>
2578+ runWrangler (
2579+ `r2 bucket lock add ${ bucketName } --id rule-age --prefix prefix-age --lock-days one`
2580+ )
2581+ ) . rejects . toThrowErrorMatchingInlineSnapshot (
2582+ `[Error: Days must be a number.]`
2583+ ) ;
2584+ } ) ;
2585+ it ( "it should fail an age lock rule using command-line arguments with invalid negative age" , async ( ) => {
25392586 setIsTTY ( true ) ;
25402587 const bucketName = "my-bucket" ;
2541- const ruleIdAge = "rule-age" ;
2542- const prefixAge = "prefix-age" ;
2543- const conditionTypeAge = "Age" ;
2544- const conditionValueAge = "one" ;
25452588
25462589 mockBucketLockPutNew ( bucketName , [
25472590 {
2548- id : ruleIdAge ,
2591+ id : "rule-age" ,
25492592 enabled : true ,
2550- prefix : prefixAge ,
2593+ prefix : "prefix-age" ,
25512594 condition : {
2552- type : conditionTypeAge ,
2595+ type : "Age" ,
25532596 maxAgeSeconds : 86400 ,
25542597 } ,
25552598 } ,
25562599 ] ) ;
25572600 // age
25582601 await expect ( ( ) =>
25592602 runWrangler (
2560- `r2 bucket lock add ${ bucketName } --id ${ ruleIdAge } --prefix ${ prefixAge } --lock-days ${ conditionValueAge } `
2603+ `r2 bucket lock add ${ bucketName } --id rule-age --prefix prefix-age --lock-days -10 `
25612604 )
25622605 ) . rejects . toThrowErrorMatchingInlineSnapshot (
2563- `[Error: Must be a positive number: ${ conditionValueAge } ]`
2606+ `[Error: Days must be a positive number: -10 ]`
25642607 ) ;
25652608 } ) ;
25662609 it ( "it should add a date lock rule using command-line arguments" , async ( ) => {
25672610 setIsTTY ( true ) ;
25682611 const bucketName = "my-bucket" ;
2569- const ruleIdDate = "rule-date" ;
2570- const prefixDate = "prefix-date" ;
2571- const conditionTypeDate = "Date" ;
2572- const conditionValueDate = "2025-01-30" ;
25732612
25742613 mockBucketLockPutNew ( bucketName , [
25752614 {
2576- id : ruleIdDate ,
2615+ id : "rule-date" ,
25772616 enabled : true ,
2578- prefix : prefixDate ,
2617+ prefix : "prefix-date" ,
25792618 condition : {
2580- type : conditionTypeDate ,
2619+ type : "Date" ,
25812620 date : "2025-01-30T00:00:00.000Z" ,
25822621 } ,
25832622 } ,
25842623 ] ) ;
25852624 // date
25862625 await runWrangler (
2587- `r2 bucket lock add ${ bucketName } --id ${ ruleIdDate } --prefix ${ prefixDate } --lock-date ${ conditionValueDate } `
2626+ `r2 bucket lock add ${ bucketName } --id rule-date --prefix prefix-date --lock-date 2025-01-30 `
25882627 ) ;
25892628 expect ( std . out ) . toMatchInlineSnapshot ( `
25902629 "Adding lock rule 'rule-date' to bucket 'my-bucket'...
25912630 ✨ Added lock rule 'rule-date' to bucket 'my-bucket'."
25922631 ` ) ;
25932632 } ) ;
2594- it ( "it should add a date lock rule using command-line arguments" , async ( ) => {
2633+ it ( "it should fail to add an invalid date lock rule using command-line arguments" , async ( ) => {
25952634 setIsTTY ( true ) ;
25962635 const bucketName = "my-bucket" ;
2597- const ruleIdDate = "rule-date" ;
2598- const prefixDate = "prefix-date" ;
2599- const conditionTypeDate = "Date" ;
2600- const conditionValueDate = "January 30, 2025" ;
26012636
2602- mockBucketLockPutNew ( bucketName , [
2603- {
2604- id : ruleIdDate ,
2605- enabled : true ,
2606- prefix : prefixDate ,
2607- condition : {
2608- type : conditionTypeDate ,
2609- date : "2025-01-30T00:00:00.000Z" ,
2610- } ,
2611- } ,
2612- ] ) ;
2637+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
26132638 // date
26142639 await expect ( ( ) =>
26152640 runWrangler (
2616- `r2 bucket lock add ${ bucketName } --id ${ ruleIdDate } --prefix ${ prefixDate } --lock-date ' ${ conditionValueDate } ' `
2641+ `r2 bucket lock add ${ bucketName } --id "rule-date" --prefix "prefix-date" --lock-date "January 30, 2025" `
26172642 )
26182643 ) . rejects . toThrowErrorMatchingInlineSnapshot (
2619- `[Error: Must be a valid date in the YYYY-MM-DD format: ${ conditionValueDate } ]`
2644+ `[Error: Date must be a valid date in the YYYY-MM-DD format: January 30, 2025 ]`
26202645 ) ;
26212646 } ) ;
26222647 it ( "it should add an indefinite lock rule using command-line arguments" , async ( ) => {
26232648 setIsTTY ( false ) ;
26242649 const bucketName = "my-bucket" ;
2625- const ruleIdIndefinite = "rule-indefinite" ;
2626- const prefixIndefinite = "prefix-indefinite" ;
2627- const conditionTypeIndefinite = "Indefinite" ;
26282650
26292651 mockBucketLockPutNew ( bucketName , [
26302652 {
2631- id : ruleIdIndefinite ,
2653+ id : "rule-indefinite" ,
26322654 enabled : true ,
2633- prefix : prefixIndefinite ,
2655+ prefix : "prefix-indefinite" ,
26342656 condition : {
2635- type : conditionTypeIndefinite ,
2657+ type : "Indefinite" ,
26362658 } ,
26372659 } ,
26382660 ] ) ;
26392661
26402662 mockConfirm ( {
26412663 text :
2642- `Are you sure you want to add lock rule '${ ruleIdIndefinite } ' to bucket '${ bucketName } ' without an expiration? ` +
2664+ `Are you sure you want to add lock rule 'rule-indefinite ' to bucket '${ bucketName } ' without an expiration? ` +
26432665 `The lock rule will apply to all matching objects indefinitely.` ,
26442666 result : true ,
26452667 } ) ;
26462668
26472669 await runWrangler (
2648- `r2 bucket lock add ${ bucketName } --id ${ ruleIdIndefinite } --prefix ${ prefixIndefinite } `
2670+ `r2 bucket lock add ${ bucketName } --id rule-indefinite --prefix prefix-indefinite `
26492671 ) ;
26502672 expect ( std . out ) . toMatchInlineSnapshot ( `
26512673 "? Are you sure you want to add lock rule 'rule-indefinite' to bucket 'my-bucket' without an expiration? The lock rule will apply to all matching objects indefinitely.
@@ -2654,6 +2676,18 @@ describe("r2", () => {
26542676 ✨ Added lock rule 'rule-indefinite' to bucket 'my-bucket'."
26552677 ` ) ;
26562678 } ) ;
2679+ it ( "it should fail a lock rule without any command-line arguments" , async ( ) => {
2680+ setIsTTY ( false ) ;
2681+ const bucketName = "my-bucket" ;
2682+
2683+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
2684+ // date
2685+ await expect ( ( ) =>
2686+ runWrangler ( `r2 bucket lock add ${ bucketName } ` )
2687+ ) . rejects . toThrowErrorMatchingInlineSnapshot (
2688+ `[Error: Must specify a rule ID.]`
2689+ ) ;
2690+ } ) ;
26572691 } ) ;
26582692 describe ( "remove" , ( ) => {
26592693 it ( "should remove a lock rule as expected" , async ( ) => {
0 commit comments