@@ -469,5 +469,173 @@ describe("Builder", () => {
469469 expect ( JSON . stringify ( manifestStore ) ) . toContain ( "Test Ingredient" ) ;
470470 expect ( JSON . stringify ( manifestStore ) ) . toContain ( "thumbnail.ingredient" ) ;
471471 } ) ;
472+
473+ it ( "should perform redaction workflow like test_redaction_async" , async ( ) => {
474+ // This test mirrors the Rust test_redaction_async test
475+
476+ // Create a reader to get the parent manifest label from the existing source
477+ const reader = await Reader . fromAsset ( source ) ;
478+ const parentManifestLabel = reader . activeLabel ( ) ;
479+ expect ( parentManifestLabel ) . toBeDefined ( ) ;
480+
481+ // Create a redacted URI for the assertion we are going to redact
482+ // Using a common assertion label that might exist
483+ const assertionLabel = "stds.schema-org.CreativeWork" ;
484+ const redactedUri = `contentauth:urn:uuid:${ parentManifestLabel } /c2pa.assertions/${ assertionLabel } ` ;
485+
486+ // Create a builder with edit intent and redactions
487+ const redactionManifestDefinition = {
488+ claim_generator : "test-generator" ,
489+ claim_generator_info : [
490+ {
491+ name : "c2pa_test" ,
492+ version : "1.0.0" ,
493+ } ,
494+ ] ,
495+ title : "Test_Redaction_Manifest" ,
496+ format : "image/jpeg" ,
497+ instance_id : "1234" ,
498+ intent : "edit" ,
499+ redactions : [ redactedUri ] ,
500+ assertions : [
501+ {
502+ label : "org.test.assertion" ,
503+ data : { } ,
504+ } ,
505+ ] ,
506+ resources : { resources : { } } ,
507+ } ;
508+
509+ const builder = Builder . withJson ( redactionManifestDefinition ) ;
510+
511+ // Add a redacted action
512+ const redactedAction = {
513+ actions : [
514+ {
515+ action : "c2pa.redacted" ,
516+ } ,
517+ ] ,
518+ } ;
519+
520+ builder . addAssertion ( "c2pa.actions" , redactedAction , "Cbor" ) ;
521+
522+ // Use the callback signer like the other test
523+ const signerConfig : JsCallbackSignerConfig = {
524+ alg : "es256" ,
525+ certs : [ publicKey ] ,
526+ reserveSize : 10000 ,
527+ tsaUrl : undefined ,
528+ directCoseHandling : false ,
529+ } ;
530+ const testSigner = new TestSigner ( privateKey ) ;
531+ const signer = CallbackSigner . newSigner ( signerConfig , testSigner . sign ) ;
532+
533+ // Sign the manifest with the original image as input
534+ const dest = { buffer : null } ;
535+ const outputBuffer = await builder . signAsync ( signer , source , dest ) ;
536+ expect ( outputBuffer . length ) . toBeGreaterThan ( 0 ) ;
537+
538+ // Verify the result by reading the signed manifest
539+ const signedReader = await Reader . fromAsset ( {
540+ buffer : dest . buffer ! as Buffer ,
541+ mimeType : "image/jpeg" ,
542+ } ) ;
543+ expect ( signedReader ) . toBeDefined ( ) ;
544+
545+ // Check that the manifest was created successfully
546+ const activeManifest = signedReader . getActive ( ) ;
547+ expect ( activeManifest ) . toBeDefined ( ) ;
548+
549+ // Verify the redacted action was added
550+ const assertions = activeManifest ?. assertions ;
551+ const actionsAssertion = assertions ?. find (
552+ ( a : any ) => a . label === "c2pa.actions.v2" ,
553+ ) ;
554+ expect ( actionsAssertion ) . toBeDefined ( ) ;
555+
556+ if ( actionsAssertion && isActionsAssertion ( actionsAssertion ) ) {
557+ const actions = actionsAssertion . data . actions ;
558+ const redactedAction = actions . find (
559+ ( a : any ) => a . action === "c2pa.redacted" ,
560+ ) ;
561+ expect ( redactedAction ) . toBeDefined ( ) ;
562+ expect ( redactedAction ?. action ) . toBe ( "c2pa.redacted" ) ;
563+ }
564+ } ) ;
565+
566+ it ( "should test builder remote url" , async ( ) => {
567+ // This test mirrors the Rust test_builder_remote_url test
568+
569+ // Create a simple manifest definition similar to simple_manifest_json()
570+ const simpleManifestDefinition = {
571+ claim_generator_info : [
572+ {
573+ name : "c2pa_test" ,
574+ version : "1.0.0" ,
575+ } ,
576+ ] ,
577+ title : "Test_Manifest" ,
578+ assertions : [
579+ {
580+ label : "c2pa.actions" ,
581+ data : {
582+ actions : [
583+ {
584+ action : "c2pa.created" ,
585+ digitalSourceType : "http://c2pa.org/digitalsourcetype/empty" ,
586+ } ,
587+ ] ,
588+ } ,
589+ } ,
590+ ] ,
591+ } ;
592+
593+ const builder = Builder . withJson ( simpleManifestDefinition ) ;
594+
595+ // Set remote URL and no embed flag like the Rust test
596+ builder . setRemoteUrl ( "http://my_remote_url" ) ;
597+ builder . setNoEmbed ( true ) ;
598+
599+ // Use the callback signer
600+ const signerConfig : JsCallbackSignerConfig = {
601+ alg : "es256" ,
602+ certs : [ publicKey ] ,
603+ reserveSize : 10000 ,
604+ tsaUrl : undefined ,
605+ directCoseHandling : false ,
606+ } ;
607+ const testSigner = new TestSigner ( privateKey ) ;
608+ const signer = CallbackSigner . newSigner ( signerConfig , testSigner . sign ) ;
609+
610+ // Sign the Builder and write it to the output stream
611+ const dest = { buffer : null } ;
612+ const manifestData = await builder . signAsync ( signer , source , dest ) ;
613+
614+ // Check to make sure we have a remote url and no manifest data embedded
615+ // Reading the image directly should fail since no_embed = true
616+ // Note: This might fail due to remote URL fetch, which is expected behavior
617+ try {
618+ await Reader . fromAsset ( {
619+ buffer : dest . buffer ! as Buffer ,
620+ mimeType : "image/jpeg" ,
621+ } ) ;
622+ // If we get here, the test should fail because we expect no embedded manifest
623+ expect . fail ( "Expected Reader.fromAsset to fail when no_embed = true" ) ;
624+ } catch ( error ) {
625+ // This is expected - there should be no embedded manifest or remote fetch should fail
626+ expect ( error ) . toBeDefined ( ) ;
627+ }
628+
629+ // Now validate the manifest against the written asset using the separate manifest data
630+ const reader = await Reader . fromManifestDataAndAsset ( manifestData , {
631+ buffer : dest . buffer ! as Buffer ,
632+ mimeType : "image/jpeg" ,
633+ } ) ;
634+
635+ // Check if the manifest has the expected structure
636+ const activeManifest = reader . getActive ( ) ;
637+ expect ( activeManifest ) . toBeDefined ( ) ;
638+ expect ( activeManifest ?. title ) . toBe ( "Test_Manifest" ) ;
639+ } ) ;
472640 } ) ;
473641} ) ;
0 commit comments