@@ -495,6 +495,81 @@ func TestDocsFindReplace_MarkdownResetsInheritedStylesBeforeLeadingBold(t *testi
495495 }
496496}
497497
498+ func TestDocsFindReplace_MarkdownResetsInheritedParagraphStyle (t * testing.T ) {
499+ origDocs := newDocsService
500+ t .Cleanup (func () { newDocsService = origDocs })
501+
502+ var got docs.BatchUpdateDocumentRequest
503+ body := docBodyWithText ("Section\n " )
504+ content := body ["body" ].(map [string ]any )["content" ].([]any )
505+ content [1 ].(map [string ]any )["paragraph" ].(map [string ]any )["paragraphStyle" ] = map [string ]any {
506+ "namedStyleType" : "HEADING_2" ,
507+ }
508+
509+ docSvc , cleanup := newDocsServiceForTest (t , func (w http.ResponseWriter , r * http.Request ) {
510+ w .Header ().Set ("Content-Type" , "application/json" )
511+ switch {
512+ case r .Method == http .MethodGet && strings .HasPrefix (r .URL .Path , "/v1/documents/" ):
513+ _ = json .NewEncoder (w ).Encode (body )
514+ case r .Method == http .MethodPost && strings .HasSuffix (r .URL .Path , ":batchUpdate" ):
515+ if err := json .NewDecoder (r .Body ).Decode (& got ); err != nil {
516+ t .Fatalf ("decode batchUpdate: %v" , err )
517+ }
518+ _ = json .NewEncoder (w ).Encode (map [string ]any {"documentId" : "doc1" })
519+ default :
520+ http .NotFound (w , r )
521+ }
522+ })
523+ defer cleanup ()
524+ newDocsService = func (context.Context , string ) (* docs.Service , error ) { return docSvc , nil }
525+
526+ replacement := "## New heading\n \n Normal prose.\n \n - bullet one\n - bullet two\n "
527+ err := runKong (t , & DocsFindReplaceCmd {}, []string {
528+ "doc1" , "Section" , replacement , "--format" , "markdown" , "--first" ,
529+ }, newDocsCmdContext (t ), & RootFlags {Account : "a@b.com" })
530+ if err != nil {
531+ t .Fatalf ("docs find-replace --format markdown --first: %v" , err )
532+ }
533+
534+ var reset * docs.UpdateParagraphStyleRequest
535+ var heading * docs.UpdateParagraphStyleRequest
536+ var bullets * docs.CreateParagraphBulletsRequest
537+ for _ , req := range got .Requests {
538+ switch {
539+ case req .UpdateParagraphStyle != nil &&
540+ req .UpdateParagraphStyle .ParagraphStyle != nil &&
541+ req .UpdateParagraphStyle .ParagraphStyle .NamedStyleType == docsNamedStyleNormalText :
542+ reset = req .UpdateParagraphStyle
543+ case req .UpdateParagraphStyle != nil &&
544+ req .UpdateParagraphStyle .ParagraphStyle != nil &&
545+ req .UpdateParagraphStyle .ParagraphStyle .NamedStyleType == docsNamedStyleHeading2 :
546+ heading = req .UpdateParagraphStyle
547+ case req .CreateParagraphBullets != nil :
548+ bullets = req .CreateParagraphBullets
549+ }
550+ }
551+ if reset == nil || reset .Fields != "namedStyleType,indentStart,indentFirstLine" {
552+ t .Fatalf ("missing NORMAL_TEXT paragraph reset: %#v" , got .Requests )
553+ }
554+ if reset .ParagraphStyle .IndentStart == nil || reset .ParagraphStyle .IndentStart .Magnitude != 0 ||
555+ reset .ParagraphStyle .IndentFirstLine == nil || reset .ParagraphStyle .IndentFirstLine .Magnitude != 0 {
556+ t .Fatalf ("paragraph reset does not clear inherited list indentation: %#v" , reset .ParagraphStyle )
557+ }
558+ if heading == nil {
559+ t .Fatalf ("missing explicit HEADING_2 request: %#v" , got .Requests )
560+ }
561+ if bullets == nil {
562+ t .Fatalf ("missing native bullet request: %#v" , got .Requests )
563+ }
564+ if reset .Range .StartIndex > heading .Range .StartIndex || reset .Range .EndIndex < bullets .Range .EndIndex {
565+ t .Fatalf ("paragraph reset does not cover formatted replacement: reset=%#v heading=%#v bullets=%#v" , reset .Range , heading .Range , bullets .Range )
566+ }
567+ inserted := got .Requests [1 ].InsertText
568+ if inserted == nil || reset .Range .EndIndex != inserted .Location .Index + utf16Len (inserted .Text )+ 1 {
569+ t .Fatalf ("full-paragraph reset must include the preserved anchor terminator: reset=%#v insert=%#v" , reset .Range , inserted )
570+ }
571+ }
572+
498573func TestDocsFindReplace_MarkdownCodeBlockStartsFreshParagraphWhenInline (t * testing.T ) {
499574 origDocs := newDocsService
500575 t .Cleanup (func () { newDocsService = origDocs })
@@ -535,18 +610,18 @@ func TestDocsFindReplace_MarkdownCodeBlockStartsFreshParagraphWhenInline(t *test
535610 t .Fatalf ("expected 1 batchUpdate call, got %d" , len (batchCalls ))
536611 }
537612 reqs := batchCalls [0 ].Requests
538- if len (reqs ) != 5 {
539- t .Fatalf ("expected delete, insert, reset , code text style, and code shading requests, got %#v" , reqs )
613+ if len (reqs ) != 7 {
614+ t .Fatalf ("expected delete, insert, text/paragraph/bullet resets , code text style, and code shading requests, got %#v" , reqs )
540615 }
541616 if got := reqs [1 ].InsertText ; got == nil || got .Location .Index != 7 || got .Text != "\n line1" + docsSoftLineBreak + "line2\n " {
542617 t .Fatalf ("unexpected insert request: %#v" , got )
543618 }
544- if got := reqs [3 ].UpdateTextStyle ; got == nil || got .Range .StartIndex != 8 || got .Range .EndIndex != 20 {
619+ if got := reqs [5 ].UpdateTextStyle ; got == nil || got .Range .StartIndex != 8 || got .Range .EndIndex != 20 {
545620 t .Fatalf ("unexpected code text style request: %#v" , got )
546621 } else {
547622 assertFencedCodeTextStyle (t , got )
548623 }
549- if got := reqs [4 ].UpdateParagraphStyle ; got == nil || got .Range .StartIndex != 8 || got .Range .EndIndex != 20 {
624+ if got := reqs [6 ].UpdateParagraphStyle ; got == nil || got .Range .StartIndex != 8 || got .Range .EndIndex != 20 {
550625 t .Fatalf ("unexpected code shading request: %#v" , got )
551626 }
552627}
0 commit comments