Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add accessibility fields to requirements diagram #2915

Merged
merged 2 commits into from
Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions cypress/integration/rendering/requirement.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,69 @@ describe('Requirement diagram', () => {
);
cy.get('svg');
});

it('should render accessibility tags', function () {
const expectedTitle = 'Gantt Diagram';
const expectedAccDescription = 'Tasks for Q4';
renderGraph(
`
requirementDiagram
title: ${expectedTitle}
accDescription: ${expectedAccDescription}

requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}

functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}

performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}

element test_entity {
type: simulation
}

element test_entity2 {
type: word doc
docRef: reqs/test_entity
}


test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req <- copies - test_entity2
`,
{}
);
cy.get('svg').should((svg) => {
const el = svg.get(0);
const children = Array.from(el.children);

const titleEl = children.find(function (node) {
return node.tagName === 'title';
});
const descriptionEl = children.find(function (node) {
return node.tagName === 'desc';
});

expect(titleEl).to.exist;
expect(titleEl.textContent).to.equal(expectedTitle);
expect(descriptionEl).to.exist;
expect(descriptionEl.textContent).to.equal(expectedAccDescription);
});
});
});
106 changes: 106 additions & 0 deletions demos/requirements.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<!DOCTYPE html>
<html>

<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=">
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>

<body>


<div class="mermaid">
requirementDiagram
title This is a title
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}

functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}

performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}

interfaceRequirement test_req4 {
id: 1.2.1
text: the fourth test text.
risk: medium
verifymethod: analysis
}

physicalRequirement test_req5 {
id: 1.2.2
text: the fifth test text.
risk: medium
verifymethod: analysis
}

designConstraint test_req6 {
id: 1.2.3
text: the sixth test text.
risk: medium
verifymethod: analysis
}

element test_entity {
type: simulation
}

element test_entity2 {
type: word doc
docRef: reqs/test_entity
}

element test_entity3 {
type: "test suite"
docRef: github.com/all_the_tests
}


test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req3 - contains -> test_req4
test_req4 - derives -> test_req5
test_req5 - refines -> test_req6
test_entity3 - verifies -> test_req5
test_req <- copies - test_entity2
</div>

<script src="./mermaid.js"></script>
<script>
mermaid.initialize({
theme: 'forest',
// themeCSS: '.node rect { fill: red; }',
logLevel: 3,
securityLevel: 'loose',
flowchart: { curve: 'basis' },
gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorMargin: 50 },
// sequenceDiagram: { actorMargin: 300 } // deprecated
});
</script>

</body>

</html>
1 change: 1 addition & 0 deletions src/diagrams/class/parser/classDiagram.jison
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ Function arguments are optional: 'call <callback_name>()' simply executes 'callb

start
: mermaidDoc
| statments
| direction
| directive start
;
Expand Down
8 changes: 7 additions & 1 deletion src/diagrams/requirement/parser/requirementDiagram.jison
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
<type_directive,arg_directive>\}\%\% { this.popState(); this.popState(); return 'close_directive'; }
<arg_directive>((?:(?!\}\%\%).|\n)*) return 'arg_directive';

"title"\s[^#\n;]+ return 'title';
"accDescription"\s[^#\n;]+ return 'accDescription';

(\r?\n)+ return 'NEWLINE';
\s+ /* skip all whitespace */
\#[^\n]* /* skip comments */
Expand Down Expand Up @@ -90,7 +93,9 @@ start

directive
: openDirective typeDirective closeDirective
| openDirective typeDirective ':' argDirective closeDirective;
| openDirective typeDirective ':' argDirective closeDirective
| title {yy.setTitle($1.substring(6));$$=$1.substring(6);}
| accDescription {yy.setAccDescription($1.substring(15));$$=$1.substring(15);};

openDirective
: open_directive { yy.parseDirective('%%{', 'open_directive'); };
Expand Down Expand Up @@ -191,6 +196,7 @@ relationship
| TRACES
{ $$=yy.Relationships.TRACES;};


requirementName: unqString | qString;
id : unqString | qString;
text : unqString | qString;
Expand Down
23 changes: 23 additions & 0 deletions src/diagrams/requirement/parser/requirementDiagram.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,29 @@ describe('when parsing requirement diagram it...', function () {
expect(Object.keys(requirementDb.getRelationships()).length).toBe(0);
});

it('will use a title and accDescription', function () {
const expectedTitle = 'test title';
const expectedAccDescription = 'my chart description';
const expectedDocRef = 'test_ref';

let lines = [
`requirementDiagram`,
``,
`title ${expectedTitle}`,
`accDescription ${expectedAccDescription}`,
`element test_name {`,
`type: test_type`,
`docref: test_ref`,
`}`,
];
let doc = lines.join('\n');

reqDiagram.parser.parse(doc);

expect(requirementDb.getTitle()).toBe(expectedTitle);
expect(requirementDb.getAccDescription()).toBe(expectedAccDescription);
});

it('will accept full relationship definition', function () {
const expectedSrc = 'a';
const expectedDest = 'b';
Expand Down
27 changes: 27 additions & 0 deletions src/diagrams/requirement/requirementDb.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import * as configApi from '../../config';
import { log } from '../../logger';
import mermaidAPI from '../../mermaidAPI';
import common from '../common/common';

let relations = [];
let latestRequirement = {};
let requirements = {};
let latestElement = {};
let elements = {};
let title = '';
let accDescription = '';

const sanitizeText = (txt) => common.sanitizeText(txt, configApi.getConfig());

const RequirementType = {
REQUIREMENT: 'Requirement',
Expand Down Expand Up @@ -134,6 +139,24 @@ const clear = () => {
elements = {};
};

export const setTitle = function (txt) {
let sanitizedText = sanitizeText(txt, configApi.getConfig());
title = sanitizedText;
};

export const getTitle = function () {
return title;
};

export const setAccDescription = function (txt) {
let sanitizedText = sanitizeText(txt, configApi.getConfig());
accDescription = sanitizedText;
};

export const getAccDescription = function () {
return accDescription;
};

export default {
RequirementType,
RiskLevel,
Expand All @@ -149,6 +172,10 @@ export default {
setNewReqText,
setNewReqRisk,
setNewReqVerifyMethod,
setTitle,
getTitle,
setAccDescription,
getAccDescription,

addElement,
getElements,
Expand Down
3 changes: 3 additions & 0 deletions src/diagrams/requirement/requirementRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { parser } from './parser/requirementDiagram';
import requirementDb from './requirementDb';
import markers from './requirementMarkers';
import { getConfig } from '../../config';
import addSVGAccessibilityFields from '../../accessibility';

const conf = {};
let relCnt = 0;
Expand Down Expand Up @@ -377,6 +378,8 @@ export const draw = (text, id) => {
configureSvgSize(svg, height, width, conf.useMaxWidth);

svg.attr('viewBox', `${svgBounds.x - padding} ${svgBounds.y - padding} ${width} ${height}`);
// Adds title and description to the requirements diagram
addSVGAccessibilityFields(parser.yy, svg, id);
};

export default {
Expand Down