@@ -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 ) ) ;
@@ -2452,18 +2474,15 @@ describe("r2", () => {
24522474 } ) ;
24532475 describe ( "add" , ( ) => {
24542476 it ( "it should add a lock rule without prefix using command-line arguments" , async ( ) => {
2455- setIsTTY ( false ) ;
2477+ setIsTTY ( true ) ;
24562478 const bucketName = "my-bucket" ;
2457- const ruleId = "rule-no-prefix" ;
2458- const conditionTypeAge = "Age" ;
2459- const conditionValueAge = 1 ;
24602479
24612480 mockBucketLockPutNew ( bucketName , [
24622481 {
2463- id : ruleId ,
2482+ id : "rule-no-prefix" ,
24642483 enabled : true ,
24652484 condition : {
2466- type : conditionTypeAge ,
2485+ type : "Age" ,
24672486 maxAgeSeconds : 86400 ,
24682487 } ,
24692488 } ,
@@ -2476,159 +2495,162 @@ describe("r2", () => {
24762495 } ) ;
24772496 mockConfirm ( {
24782497 text :
2479- `Are you sure you want to add lock rule '${ ruleId } ' to bucket '${ bucketName } ' without a prefix? ` +
2498+ `Are you sure you want to add lock rule 'rule-no-prefix ' to bucket '${ bucketName } ' without a prefix? ` +
24802499 `The lock rule will apply to all objects in your bucket.` ,
24812500 result : true ,
24822501 } ) ;
24832502 await runWrangler (
2484- `r2 bucket lock add ${ bucketName } --id ${ ruleId } --lock-days ${ conditionValueAge } `
2503+ `r2 bucket lock add ${ bucketName } --id "rule-no-prefix" --lock-days 1 `
24852504 ) ;
24862505 expect ( std . out ) . toMatchInlineSnapshot ( `
2487- "? Enter a prefix for the bucket lock rule (set to \\"\\" for all prefixes)
2488- 🤖 Using default value in non-interactive context:
2489- Adding lock rule 'rule-no-prefix' to bucket 'my-bucket'...
2506+ "Adding lock rule 'rule-no-prefix' to bucket 'my-bucket'...
24902507 ✨ Added lock rule 'rule-no-prefix' to bucket 'my-bucket'."
24912508 ` ) ;
24922509 } ) ;
2510+ it ( "it should fail to add lock rule using command-line arguments without condition" , async ( ) => {
2511+ setIsTTY ( true ) ;
2512+ const bucketName = "my-bucket" ;
2513+
2514+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
2515+
2516+ mockConfirm ( {
2517+ text :
2518+ `Are you sure you want to add lock rule 'rule-not-indefinite' to bucket '${ bucketName } ' without an expiration? ` +
2519+ `The lock rule will apply to all matching objects indefinitely.` ,
2520+ result : false ,
2521+ } ) ;
2522+
2523+ await runWrangler (
2524+ `r2 bucket lock add ${ bucketName } --id 'rule-not-indefinite' --prefix prefix-not-indefinite`
2525+ ) ;
2526+ expect ( std . out ) . toMatchInlineSnapshot ( `
2527+ "Add cancelled."
2528+ ` ) ;
2529+ } ) ;
24932530 it ( "it should add an age lock rule using command-line arguments" , async ( ) => {
24942531 setIsTTY ( true ) ;
24952532 const bucketName = "my-bucket" ;
2496- const ruleIdAge = "rule-age" ;
2497- const prefixAge = "prefix-age" ;
2498- const conditionTypeAge = "Age" ;
2499- const conditionValueAge = 1 ;
25002533
25012534 mockBucketLockPutNew ( bucketName , [
25022535 {
2503- id : ruleIdAge ,
2536+ id : "rule-age" ,
25042537 enabled : true ,
2505- prefix : prefixAge ,
2538+ prefix : "prefix-age" ,
25062539 condition : {
2507- type : conditionTypeAge ,
2540+ type : "Age" ,
25082541 maxAgeSeconds : 86400 ,
25092542 } ,
25102543 } ,
25112544 ] ) ;
25122545 // age
25132546 await runWrangler (
2514- `r2 bucket lock add ${ bucketName } --id ${ ruleIdAge } --prefix ${ prefixAge } --lock-days ${ conditionValueAge } `
2547+ `r2 bucket lock add ${ bucketName } --id rule-age --prefix prefix-age --lock-days 1 `
25152548 ) ;
25162549 expect ( std . out ) . toMatchInlineSnapshot ( `
25172550 "Adding lock rule 'rule-age' to bucket 'my-bucket'...
25182551 ✨ Added lock rule 'rule-age' to bucket 'my-bucket'."
25192552 ` ) ;
25202553 } ) ;
2521- it ( "it should fail an age lock rule using command-line arguments with invalid age" , async ( ) => {
2554+ it ( "it should fail an age lock rule using command-line arguments with invalid age string" , async ( ) => {
2555+ setIsTTY ( true ) ;
2556+ const bucketName = "my-bucket" ;
2557+
2558+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
2559+ // age
2560+ await expect ( ( ) =>
2561+ runWrangler (
2562+ `r2 bucket lock add ${ bucketName } --id rule-age --prefix prefix-age --lock-days one`
2563+ )
2564+ ) . rejects . toThrowErrorMatchingInlineSnapshot (
2565+ `[Error: Days must be a number.]`
2566+ ) ;
2567+ } ) ;
2568+ it ( "it should fail an age lock rule using command-line arguments with invalid negative age" , async ( ) => {
25222569 setIsTTY ( true ) ;
25232570 const bucketName = "my-bucket" ;
2524- const ruleIdAge = "rule-age" ;
2525- const prefixAge = "prefix-age" ;
2526- const conditionTypeAge = "Age" ;
2527- const conditionValueAge = "one" ;
25282571
25292572 mockBucketLockPutNew ( bucketName , [
25302573 {
2531- id : ruleIdAge ,
2574+ id : "rule-age" ,
25322575 enabled : true ,
2533- prefix : prefixAge ,
2576+ prefix : "prefix-age" ,
25342577 condition : {
2535- type : conditionTypeAge ,
2578+ type : "Age" ,
25362579 maxAgeSeconds : 86400 ,
25372580 } ,
25382581 } ,
25392582 ] ) ;
25402583 // age
25412584 await expect ( ( ) =>
25422585 runWrangler (
2543- `r2 bucket lock add ${ bucketName } --id ${ ruleIdAge } --prefix ${ prefixAge } --lock-days ${ conditionValueAge } `
2586+ `r2 bucket lock add ${ bucketName } --id rule-age --prefix prefix-age --lock-days -10 `
25442587 )
25452588 ) . rejects . toThrowErrorMatchingInlineSnapshot (
2546- `[Error: Must be a positive number: ${ conditionValueAge } ]`
2589+ `[Error: Days must be a positive number: -10 ]`
25472590 ) ;
25482591 } ) ;
25492592 it ( "it should add a date lock rule using command-line arguments" , async ( ) => {
25502593 setIsTTY ( true ) ;
25512594 const bucketName = "my-bucket" ;
2552- const ruleIdDate = "rule-date" ;
2553- const prefixDate = "prefix-date" ;
2554- const conditionTypeDate = "Date" ;
2555- const conditionValueDate = "2025-01-30" ;
25562595
25572596 mockBucketLockPutNew ( bucketName , [
25582597 {
2559- id : ruleIdDate ,
2598+ id : "rule-date" ,
25602599 enabled : true ,
2561- prefix : prefixDate ,
2600+ prefix : "prefix-date" ,
25622601 condition : {
2563- type : conditionTypeDate ,
2602+ type : "Date" ,
25642603 date : "2025-01-30T00:00:00.000Z" ,
25652604 } ,
25662605 } ,
25672606 ] ) ;
25682607 // date
25692608 await runWrangler (
2570- `r2 bucket lock add ${ bucketName } --id ${ ruleIdDate } --prefix ${ prefixDate } --lock-date ${ conditionValueDate } `
2609+ `r2 bucket lock add ${ bucketName } --id rule-date --prefix prefix-date --lock-date 2025-01-30 `
25712610 ) ;
25722611 expect ( std . out ) . toMatchInlineSnapshot ( `
25732612 "Adding lock rule 'rule-date' to bucket 'my-bucket'...
25742613 ✨ Added lock rule 'rule-date' to bucket 'my-bucket'."
25752614 ` ) ;
25762615 } ) ;
2577- it ( "it should add a date lock rule using command-line arguments" , async ( ) => {
2616+ it ( "it should fail to add an invalid date lock rule using command-line arguments" , async ( ) => {
25782617 setIsTTY ( true ) ;
25792618 const bucketName = "my-bucket" ;
2580- const ruleIdDate = "rule-date" ;
2581- const prefixDate = "prefix-date" ;
2582- const conditionTypeDate = "Date" ;
2583- const conditionValueDate = "January 30, 2025" ;
25842619
2585- mockBucketLockPutNew ( bucketName , [
2586- {
2587- id : ruleIdDate ,
2588- enabled : true ,
2589- prefix : prefixDate ,
2590- condition : {
2591- type : conditionTypeDate ,
2592- date : "2025-01-30T00:00:00.000Z" ,
2593- } ,
2594- } ,
2595- ] ) ;
2620+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
25962621 // date
25972622 await expect ( ( ) =>
25982623 runWrangler (
2599- `r2 bucket lock add ${ bucketName } --id ${ ruleIdDate } --prefix ${ prefixDate } --lock-date ' ${ conditionValueDate } ' `
2624+ `r2 bucket lock add ${ bucketName } --id "rule-date" --prefix "prefix-date" --lock-date "January 30, 2025" `
26002625 )
26012626 ) . rejects . toThrowErrorMatchingInlineSnapshot (
2602- `[Error: Must be a valid date in the YYYY-MM-DD format: ${ conditionValueDate } ]`
2627+ `[Error: Date must be a valid date in the YYYY-MM-DD format: January 30, 2025 ]`
26032628 ) ;
26042629 } ) ;
26052630 it ( "it should add an indefinite lock rule using command-line arguments" , async ( ) => {
26062631 setIsTTY ( false ) ;
26072632 const bucketName = "my-bucket" ;
2608- const ruleIdIndefinite = "rule-indefinite" ;
2609- const prefixIndefinite = "prefix-indefinite" ;
2610- const conditionTypeIndefinite = "Indefinite" ;
26112633
26122634 mockBucketLockPutNew ( bucketName , [
26132635 {
2614- id : ruleIdIndefinite ,
2636+ id : "rule-indefinite" ,
26152637 enabled : true ,
2616- prefix : prefixIndefinite ,
2638+ prefix : "prefix-indefinite" ,
26172639 condition : {
2618- type : conditionTypeIndefinite ,
2640+ type : "Indefinite" ,
26192641 } ,
26202642 } ,
26212643 ] ) ;
26222644
26232645 mockConfirm ( {
26242646 text :
2625- `Are you sure you want to add lock rule '${ ruleIdIndefinite } ' to bucket '${ bucketName } ' without an expiration? ` +
2647+ `Are you sure you want to add lock rule 'rule-indefinite ' to bucket '${ bucketName } ' without an expiration? ` +
26262648 `The lock rule will apply to all matching objects indefinitely.` ,
26272649 result : true ,
26282650 } ) ;
26292651
26302652 await runWrangler (
2631- `r2 bucket lock add ${ bucketName } --id ${ ruleIdIndefinite } --prefix ${ prefixIndefinite } `
2653+ `r2 bucket lock add ${ bucketName } --id rule-indefinite --prefix prefix-indefinite `
26322654 ) ;
26332655 expect ( std . out ) . toMatchInlineSnapshot ( `
26342656 "? 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.
@@ -2637,6 +2659,18 @@ describe("r2", () => {
26372659 ✨ Added lock rule 'rule-indefinite' to bucket 'my-bucket'."
26382660 ` ) ;
26392661 } ) ;
2662+ it ( "it should fail a lock rule without any command-line arguments" , async ( ) => {
2663+ setIsTTY ( false ) ;
2664+ const bucketName = "my-bucket" ;
2665+
2666+ mockBucketLockGetExistingRules ( bucketName , [ ] ) ;
2667+ // date
2668+ await expect ( ( ) =>
2669+ runWrangler ( `r2 bucket lock add ${ bucketName } ` )
2670+ ) . rejects . toThrowErrorMatchingInlineSnapshot (
2671+ `[Error: Must specify a rule ID.]`
2672+ ) ;
2673+ } ) ;
26402674 } ) ;
26412675 describe ( "remove" , ( ) => {
26422676 it ( "should remove a lock rule as expected" , async ( ) => {
0 commit comments