add CLI test

This commit is contained in:
Júlio César Batista 2023-04-06 15:16:32 -03:00
parent 4b2041f759
commit 37c46b7435
No known key found for this signature in database
GPG key ID: 10C4B861BF314878
4 changed files with 126 additions and 24 deletions

View file

@ -9,6 +9,7 @@ import (
"time"
"oss.terrastruct.com/d2/d2cli"
"oss.terrastruct.com/d2/lib/pptx"
"oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/diff"
"oss.terrastruct.com/util-go/xmain"
@ -234,6 +235,32 @@ layers: {
testdataIgnoreDiff(t, ".pdf", pdf)
},
},
{
name: "how_to_solve_problems_pptx",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {
writeFile(t, dir, "in.d2", `how to solve a hard problem?
steps: {
1: {
w: write down the problem
}
2: {
w -> t
t: think really hard about it
}
3: {
t -> w2
w2: write down the solution
}
}
`)
err := runTestMain(t, ctx, dir, env, "in.d2", "how_to_solve_problems.pptx")
assert.Success(t, err)
file := readFile(t, dir, "how_to_solve_problems.pptx")
err = pptx.Validate(file, 4)
assert.Success(t, err)
},
},
{
name: "stdin",
run: func(t *testing.T, ctx context.Context, dir string, env *xos.Env) {

View file

@ -5,7 +5,6 @@ import (
"bytes"
_ "embed"
"fmt"
"io"
"strings"
"time"
)
@ -19,21 +18,12 @@ func copyPptxTemplateTo(w *zip.Writer) error {
reader := bytes.NewReader(pptx_template)
zipReader, err := zip.NewReader(reader, reader.Size())
if err != nil {
fmt.Printf("%v", err)
fmt.Printf("error creating zip reader: %v", err)
}
for _, f := range zipReader.File {
fw, err := w.Create(f.Name)
if err != nil {
return err
}
fr, err := f.Open()
if err != nil {
return err
}
_, err = io.Copy(fw, fr)
if err != nil {
return err
if err := w.Copy(f); err != nil {
return fmt.Errorf("error copying %s: %v", f.Name, err)
}
}
return nil
@ -116,6 +106,7 @@ func getPresentationXml(slideFileNames []string) string {
builder.WriteString("<p:sldIdLst>")
for i, name := range slideFileNames {
// in the exported presentation, the first slide ID was 256, so keeping it here for compatibility
builder.WriteString(fmt.Sprintf(`<p:sldId id="%d" r:id="%s" />`, 256+i, name))
}
builder.WriteString("</p:sldIdLst>")

View file

@ -88,10 +88,12 @@ func (p *Presentation) SaveTo(filePath string) error {
return err
}
defer f.Close()
zipFile := zip.NewWriter(f)
defer zipFile.Close()
zipWriter := zip.NewWriter(f)
defer zipWriter.Close()
copyPptxTemplateTo(zipFile)
if err = copyPptxTemplateTo(zipWriter); err != nil {
return err
}
var slideFileNames []string
for i, slide := range p.Slides {
@ -99,7 +101,7 @@ func (p *Presentation) SaveTo(filePath string) error {
slideFileName := fmt.Sprintf("slide%d", i+1)
slideFileNames = append(slideFileNames, slideFileName)
imageWriter, err := zipFile.Create(fmt.Sprintf("ppt/media/%s.png", imageId))
imageWriter, err := zipWriter.Create(fmt.Sprintf("ppt/media/%s.png", imageId))
if err != nil {
return err
}
@ -108,13 +110,13 @@ func (p *Presentation) SaveTo(filePath string) error {
return err
}
err = addFile(zipFile, fmt.Sprintf("ppt/slides/_rels/%s.xml.rels", slideFileName), getRelsSlideXml(imageId))
err = addFile(zipWriter, fmt.Sprintf("ppt/slides/_rels/%s.xml.rels", slideFileName), getRelsSlideXml(imageId))
if err != nil {
return err
}
err = addFile(
zipFile,
zipWriter,
fmt.Sprintf("ppt/slides/%s.xml", slideFileName),
getSlideXml(slide.BoardPath, imageId, slide.ImageTop, slide.ImageLeft, slide.ImageWidth, slide.ImageHeight),
)
@ -123,27 +125,27 @@ func (p *Presentation) SaveTo(filePath string) error {
}
}
err = addFile(zipFile, "[Content_Types].xml", getContentTypesXml(slideFileNames))
err = addFile(zipWriter, "[Content_Types].xml", getContentTypesXml(slideFileNames))
if err != nil {
return err
}
err = addFile(zipFile, "ppt/_rels/presentation.xml.rels", getPresentationXmlRels(slideFileNames))
err = addFile(zipWriter, "ppt/_rels/presentation.xml.rels", getPresentationXmlRels(slideFileNames))
if err != nil {
return err
}
err = addFile(zipFile, "ppt/presentation.xml", getPresentationXml(slideFileNames))
err = addFile(zipWriter, "ppt/presentation.xml", getPresentationXml(slideFileNames))
if err != nil {
return err
}
err = addFile(zipFile, "docProps/core.xml", getCoreXml(p.Title, p.Subject, p.Description, p.Creator))
err = addFile(zipWriter, "docProps/core.xml", getCoreXml(p.Title, p.Subject, p.Description, p.Creator))
if err != nil {
return err
}
err = addFile(zipFile, "docProps/app.xml", getAppXml(p.Slides, p.D2Version))
err = addFile(zipWriter, "docProps/app.xml", getAppXml(p.Slides, p.D2Version))
if err != nil {
return err
}

82
lib/pptx/validate.go Normal file
View file

@ -0,0 +1,82 @@
package pptx
import (
"archive/zip"
"bytes"
"encoding/xml"
"fmt"
"io"
"strings"
)
func Validate(pptxContent []byte, nSlides int) error {
reader := bytes.NewReader(pptxContent)
zipReader, err := zip.NewReader(reader, reader.Size())
if err != nil {
fmt.Printf("error reading pptx content: %v", err)
}
expectedCount := getExpectedPptxFileCount(nSlides)
if len(zipReader.File) != expectedCount {
return fmt.Errorf("expected %d files, got %d", expectedCount, len(zipReader.File))
}
for i := 0; i < nSlides; i++ {
if err := checkFile(zipReader, fmt.Sprintf("ppt/slides/slide%d.xml", i+1)); err != nil {
return err
}
if err := checkFile(zipReader, fmt.Sprintf("ppt/slides/_rels/slide%d.xml.rels", i+1)); err != nil {
return err
}
if err := checkFile(zipReader, fmt.Sprintf("ppt/media/slide%dImage.png", i+1)); err != nil {
return err
}
}
for _, file := range zipReader.File {
if !strings.Contains(file.Name, ".xml") {
continue
}
// checks if the XML content is valid
f, err := file.Open()
if err != nil {
return fmt.Errorf("error opening %s: %v", file.Name, err)
}
decoder := xml.NewDecoder(f)
for {
if err := decoder.Decode(new(interface{})); err != nil {
if err == io.EOF {
break
}
return fmt.Errorf("error parsing xml content in %s: %v", file.Name, err)
}
}
defer f.Close()
}
return nil
}
func checkFile(reader *zip.Reader, fname string) error {
f, err := reader.Open(fname)
if err != nil {
return fmt.Errorf("error opening file %s: %v", fname, err)
}
defer f.Close()
if _, err = f.Stat(); err != nil {
return fmt.Errorf("error getting file info %s: %v", fname, err)
}
return nil
}
func getExpectedPptxFileCount(nSlides int) int {
reader := bytes.NewReader(pptx_template)
zipReader, err := zip.NewReader(reader, reader.Size())
if err != nil {
return -1
}
baseFiles := len(zipReader.File)
presentationFiles := 5 // presentation, rels, app, core, content types
slideFiles := 3 * nSlides // slides, rels, images
return baseFiles + presentationFiles + slideFiles
}