From 1de07e32581920a185957f17d9bf595d6c4a48ff Mon Sep 17 00:00:00 2001 From: Aadityavardhan Singh Date: Mon, 22 Dec 2025 12:58:57 +0530 Subject: [PATCH] test: add regression test for nested optionals (Issue #49) Signed-off-by: Aadityavardhan Singh --- .../TemplateMarkInterpreter.test.ts.snap | 642 ++++++++++++++++++ test/templates/good/optional-nested/data.json | 51 ++ test/templates/good/optional-nested/model.cto | 47 ++ .../good/optional-nested/template.md | 60 ++ 4 files changed, 800 insertions(+) create mode 100644 test/templates/good/optional-nested/data.json create mode 100644 test/templates/good/optional-nested/model.cto create mode 100644 test/templates/good/optional-nested/template.md diff --git a/test/__snapshots__/TemplateMarkInterpreter.test.ts.snap b/test/__snapshots__/TemplateMarkInterpreter.test.ts.snap index c439263..ed8f2e0 100644 --- a/test/__snapshots__/TemplateMarkInterpreter.test.ts.snap +++ b/test/__snapshots__/TemplateMarkInterpreter.test.ts.snap @@ -3128,6 +3128,648 @@ exports[`templatemark interpreter should generate optional_comprehensive 1`] = ` } `; +exports[`templatemark interpreter should generate optional-nested 1`] = ` +{ + "$class": "org.accordproject.commonmark@0.5.0.Document", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Heading", + "level": "1", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Optional Test", + }, + ], + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Clause", + "elementType": "org.example.ap2.mandate@1.1.1.AP2MandateData", + "name": "mandate", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.BlockQuote", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Strong", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Mandate ID:", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": " ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "mandateId", + "value": "mandate-2025-10-A2B-001", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Heading", + "level": "2", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Parties", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "idKey", + "value": "id2", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Optional", + "elementType": "org.example.ap2.mandate@1.1.1.PedUri", + "hasSome": true, + "name": "pedUri", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "{{pedUri.uri}}uri", + }, + ], + "whenNone": [], + "whenSome": [], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "idKey", + "value": "id2", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "uri:", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "uri", + "value": "http://someurl.com?a=1", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Optional", + "elementType": "org.example.ap2.mandate@1.1.1.PedUri", + "hasSome": true, + "name": "pedUri", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "text", + }, + ], + "whenNone": [], + "whenSome": [], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "idKey", + "value": "id2", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Optional", + "elementType": "org.example.ap2.mandate@1.1.1.PedUri", + "hasSome": true, + "name": "pedUri", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "uri", + "value": "http://someurl.com?a=1", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "uri", + }, + ], + "whenNone": [], + "whenSome": [], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "idKey", + "value": "id2", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Optional", + "elementType": "org.example.ap2.mandate@1.1.1.PedUri", + "hasSome": true, + "name": "pedUri", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "{{this.uri}}uri", + }, + ], + "whenNone": [], + "whenSome": [], + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Strong", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Payee:", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Formula", + "dependencies": [], + "name": "formula_7f77a1fc3bf46ee7bd9f1eee1c8967f3d0ccaeddc878a7673b584fdc4f00f042", + "value": ""- PED: http://someurl.com?a=1"", + }, + ], + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.BlockQuote", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "A general sample that uses a range of features", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Heading", + "level": "3", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Welcome ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "name", + "value": "John Doe", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "!", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Image", + "destination": "https://avatars.githubusercontent.com/u/29445438?s=64", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "AP Logo", + }, + ], + "title": "", + }, + ], + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Clause", + "elementType": "org.example.ap2.mandate@1.1.1.Address", + "name": "address", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Heading", + "level": "4", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Address", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.BlockQuote", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "line1", + "value": "1 Main Street", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": ",", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Linebreak", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "city", + "value": "Boson", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": ", ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "state", + "value": "MA", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": ",", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Linebreak", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "country", + "value": "USA", + }, + ], + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.List", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Item", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "You are ", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Emph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "Integer", + "name": "age", + "value": "42", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": " years old", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Item", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Your monthly salary is ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.FormattedVariable", + "elementType": "org.accordproject.money@0.3.0.MonetaryAmount", + "format": "0,0.00 CCC", + "name": "salary", + "value": "1,500.00 EUR", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Item", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Your favorite colours are ", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "red, green, and blue", + }, + ], + }, + ], + }, + ], + "tight": "true", + "type": "bullet", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Clause", + "elementType": "org.example.ap2.mandate@1.1.1.Order", + "name": "order", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Heading", + "level": "2", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Orders", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Your last order was placed ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.FormattedVariable", + "elementType": "DateTime", + "format": "D MMMM YYYY", + "name": "createdAt", + "value": "1 May 2023", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": " (", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Formula", + "dependencies": [], + "name": "formula_87067c9bed3b3c592c46445b8d60c223615c5dbc49d2ab1bacecb1e78350c991", + "value": "-44", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": " days ago).", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.List", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Item", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "Integer", + "name": "quantity", + "value": "3", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "x ", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Emph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "sku", + "value": "ABC-123", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": " @ £", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.FormattedVariable", + "elementType": "Double", + "format": "0,0.00", + "name": "price", + "value": "29.99", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Item", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "Integer", + "name": "quantity", + "value": "5", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "x ", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Emph", + "nodes": [ + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "String", + "name": "sku", + "value": "DEF-456", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": " @ £", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.FormattedVariable", + "elementType": "Double", + "format": "0,0.00", + "name": "price", + "value": "19.99", + }, + ], + }, + ], + }, + ], + "tight": "true", + "type": "bullet", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Order total: ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Formula", + "dependencies": [], + "name": "formula_a6c3eb22d929c718c1ff356e4980b97a736d405a04fbb541ba5db1728cb3a579", + "value": ""£189.92"", + }, + ], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Heading", + "level": "3", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Verification", + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Checking logic for top-level optionals:", + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Softbreak", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Optional", + "elementType": "Integer", + "hasSome": true, + "name": "age", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Age is provided as ", + }, + { + "$class": "org.accordproject.ciceromark@0.6.0.Variable", + "elementType": "Integer", + "name": "this", + "value": "42", + }, + ], + "whenNone": [], + "whenSome": [], + }, + ], + }, + { + "$class": "org.accordproject.commonmark@0.5.0.Paragraph", + "nodes": [ + { + "$class": "org.accordproject.commonmark@0.5.0.Text", + "text": "Thank you.", + }, + ], + }, + ], + }, + ], + "xmlns": "http://commonmark.org/xml/1.0", +} +`; + exports[`templatemark interpreter should generate paragraph 1`] = ` { "$class": "org.accordproject.commonmark@0.5.0.Document", diff --git a/test/templates/good/optional-nested/data.json b/test/templates/good/optional-nested/data.json new file mode 100644 index 0000000..d37b48e --- /dev/null +++ b/test/templates/good/optional-nested/data.json @@ -0,0 +1,51 @@ +{ + "$class": "org.example.ap2.mandate@1.1.1.TemplateData", + "name": "John Doe", + "address": { + "line1": "1 Main Street", + "city": "Boson", + "state": "MA", + "country": "USA" + }, + "age": 42, + "salary": { + "$class": "org.accordproject.money@0.3.0.MonetaryAmount", + "doubleValue": 1500, + "currencyCode": "EUR" + }, + "favoriteColors": [ + "red", + "green", + "blue" + ], + "order": { + "createdAt": "2023-05-01", + "$class": "org.example.ap2.mandate@1.1.1.Order", + "orderLines": [ + { + "$class": "org.example.ap2.mandate@1.1.1.OrderLine", + "sku": "ABC-123", + "quantity": 3, + "price": 29.99 + }, + { + "$class": "org.example.ap2.mandate@1.1.1.OrderLine", + "sku": "DEF-456", + "quantity": 5, + "price": 19.99 + } + ] + }, + "mandate": { + "$class": "org.example.ap2.mandate@1.1.1.AP2MandateData", + "mandateId": "mandate-2025-10-A2B-001", + "payee": { + "$class": "org.example.ap2.mandate@1.1.1.Merchant", + "idKey":"id2", + "pedUri":{ + "$class":"org.example.ap2.mandate@1.1.1.PedUri", + "uri":"http://someurl.com?a=1" + } + } + } + } \ No newline at end of file diff --git a/test/templates/good/optional-nested/model.cto b/test/templates/good/optional-nested/model.cto new file mode 100644 index 0000000..d570412 --- /dev/null +++ b/test/templates/good/optional-nested/model.cto @@ -0,0 +1,47 @@ +namespace org.example.ap2.mandate@1.1.1 +import org.accordproject.money@0.3.0.{MonetaryAmount} from https://models.accordproject.org/money@0.3.0.cto +import org.accordproject.time@0.3.0.{Duration} from https://models.accordproject.org/time@0.3.0.cto +import org.accordproject.party@0.2.0.{Party} from https://models.accordproject.org/accordproject/party@0.2.0.cto + +concept Address { + o String line1 + o String city + o String state + o String country +} + +concept OrderLine { + o String sku + o Integer quantity + o Double price +} + +concept Order { + o DateTime createdAt + o OrderLine[] orderLines +} + +concept PedUri identified by uri{ + o String uri +} + +participant Merchant identified by idKey { + o String idKey + o PedUri pedUri optional +} + +concept AP2MandateData { + o String mandateId + o Merchant payee +} + +@template +concept TemplateData { + o String name + o Address address + o Integer age optional + o MonetaryAmount salary + o String[] favoriteColors + o AP2MandateData mandate + o Order order +} \ No newline at end of file diff --git a/test/templates/good/optional-nested/template.md b/test/templates/good/optional-nested/template.md new file mode 100644 index 0000000..b0e83d6 --- /dev/null +++ b/test/templates/good/optional-nested/template.md @@ -0,0 +1,60 @@ +# Optional Test + +{{#clause mandate}} +> **Mandate ID:** {{mandateId}} + + +## Parties + +{{#with payee}}{{idKey}}{{#optional pedUri}}{{pedUri.uri}}uri{{else}}No pedUri{{/optional}}{{/with}} +{{#with payee}}{{idKey}}{{#with pedUri}}uri:{{uri}}{{/with}}{{/with}} +{{#with payee}}{{#optional pedUri}}text{{/optional}}{{/with}} +{{#with payee}}{{idKey}}{{#optional pedUri}}{{uri}}uri{{else}}No pedUri{{/optional}}{{/with}} +{{#with payee}}{{idKey}}{{#optional pedUri}}{{this.uri}}uri{{else}}No pedUri{{/optional}}{{/with}} + +**Payee:** +{{#with payee}} +{{% + if (mandate && mandate.payee && mandate.payee.pedUri) { + return "- PED: " + mandate.payee.pedUri.uri; + } else { + return ""; + } +%}}{{/with}} + +{{/clause}} + +> A general sample that uses a range of features +### Welcome {{name}}! + +![AP Logo](https://avatars.githubusercontent.com/u/29445438?s=64) + +{{#clause address}} +#### Address +> {{line1}}, + {{city}}, {{state}}, + {{country}} + {{/clause}} + +- You are *{{age}}* years old +- Your monthly salary is {{salary as "0,0.00 CCC"}} +- Your favorite colours are {{#join favoriteColors}} + +{{#clause order}} +## Orders +Your last order was placed {{createdAt as "D MMMM YYYY"}} ({{% return now.diff(order.createdAt, 'day')%}} days ago). + +{{#ulist orderLines}} +- {{quantity}}x _{{sku}}_ @ £{{price as "0,0.00"}} +{{/ulist}} +Order total: {{% return '£' + order.orderLines.map(ol => ol.price * ol.quantity).reduce((sum, cur) => sum + cur).toFixed(2);%}} + +{{/clause}} + +### Verification +Checking logic for top-level optionals: +{{#optional age}}Age is provided as {{this}}{{else}}Age is hidden{{/optional}} + + + +Thank you.