diff --git a/.travis.yml b/.travis.yml index e955fa4..57d6366 100644 --- a/.travis.yml +++ b/.travis.yml @@ -47,4 +47,40 @@ matrix: - xvfb - libx11-dev - libxkbfile-dev - install: false \ No newline at end of file + install: skip + + - dist: bionic + + services: + - xvfb + + language: node_js + node_js: '10' + before_script: + - cd server + - mvn install -U + - cd ../client + - fluxbox >/dev/null 2>&1 & + - sleep 3 + - yarn + script: yarn e2etest + cache: + yarn: true + directories: + - node_modules + env: + global: + - CXX=g++-4.8 + - NODE_OPTIONS="--max_old_space_size=4096" + addons: + firefox: latest + chrome: stable + apt: + update: true + packages: + - g++-4.8 + - libsecret-1-dev + - xvfb + - libx11-dev + - libxkbfile-dev + install: skip \ No newline at end of file diff --git a/client/package.json b/client/package.json index 772a0c9..0a401e1 100644 --- a/client/package.json +++ b/client/package.json @@ -11,7 +11,7 @@ "publish:next": "lerna publish --exact --canary=next --npm-tag=next --yes", "theia:start": "cd browser-app && yarn start", "testcafe:start": "testcafe chrome tests/test.ts", - "e2etest": "npm-run-all --parallel --aggregate-output theia:start testcafe:start" + "e2etest": "npm-run-all --parallel --race --aggregate-output theia:start testcafe:start" }, "devDependencies": { "lerna": "2.4.0", diff --git a/client/tests/test.ts b/client/tests/test.ts index a9ecd33..5b6f4c9 100644 --- a/client/tests/test.ts +++ b/client/tests/test.ts @@ -14,154 +14,97 @@ import { Selector } from "testcafe"; import * as config from "./config.json"; // Converts Windows paths to all / for integration with theia -const relPathToWorkspace = resolve(join(__dirname, '..', 'workspace')).replace(/\\/g, "/"); - - -class Helper { - static load = async t => { - await t - .wait(5000); - await Selector('.p-MenuBar-content', { visibilityCheck: true }); - } - - static emptyEcore = () => { - return Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('empty.ecore'); - } - - static glspGraphEcore = () => { - return Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('glsp-graph.ecore'); - } - - static wsSelect = () => { - return Selector('#shell-tab-explorer-view-container'); - } +const relPathToWorkspace = resolve(join(__dirname, 'workspace')).replace(/\\/g, "/"); + +const selectors = { + emptyEcore: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('empty.ecore'), + testEcore: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('test.ecore'), + testEnotation: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('test.enotation'), + testNodesOnlyEcore: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('testNodesOnly.ecore'), + testNodesOnlyEnotation: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('testNodesOnly.enotation'), + testNodesWithAttributesEcore: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('testNodesWithAttributes.ecore'), + testNodesWithAttributesEnotation: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('testNodesWithAttributes.enotation'), + umlEcore: Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('UML.ecore'), + wsSelect: Selector('#shell-tab-explorer-view-container'), + svgCanvas: Selector('svg.sprotty-graph'), + eraser: Selector('.fas.fa-eraser.fa-xs'), + edgePoints: Selector('.sprotty-edge.ecore-edge.selected').child().withAttribute('data-kind', 'manhattan-50%'), + duplicateFile: Selector('.p-Menu-itemLabel').withText('Duplicate'), + deleteFile: Selector('.p-Menu-itemLabel').withText('Delete'), + renameFile: Selector('.p-Menu-itemLabel').withText('Rename'), + okButton: Selector('.theia-button.main').withText('OK'), + renameInput: Selector('div.dialogContent > input'), + openWith: Selector('.p-Menu-itemLabel').withText('Open With'), + codeEditor: Selector('.p-Menu-itemLabel').withText('Code Editor'), + line: Selector('.view-lines'), + input: Selector('div.label-edit input'), + attribute: Selector('div.tool-group > div.tool-button').withText("Attribute"), + literal: Selector('div.tool-group > div.tool-button').withText("Literal"), } -class CreateHelper { - - constructor(private t: TestController) { - } - async createNode(name) { - const selector = Selector('div.tool-group > div.tool-button').withText(name); - const svgCanvas = Selector('svg.sprotty-graph'); - await this.t.click(selector) - .click(svgCanvas); - } - - async createClass() { - return this.createNode('Class'); - } - - async createAbstract() { - return this.createNode('Abstract'); - } - - async createInterface() { - return this.createNode('Interface'); - } - - async createEnum() { - return this.createNode('Enum'); - } +const nodesSelector = { + classNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('Class'), + abstractNode: Selector('g.node.ecore-node.abstract text.name.sprotty-label').withText('Abstract'), + enumNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('Enum'), + interfaceNode: Selector('g.node.ecore-node.interface text.name.sprotty-label').withText('Interface'), + dataTypeNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('DataType') +}; - async createAllNodeTypes() { - const emptyEcore = Helper.emptyEcore(); - const wsSelect = Helper.wsSelect(); - - await this.t - .click(wsSelect) - .click(emptyEcore); - await this.createClass(); - await this.createAbstract(); - await this.createEnum(); - await this.createInterface(); - } +const edgeSelector = { + inheritanceEdge: Selector('g.sprotty-edge.ecore-edge.inheritance'), + containmentEdge: Selector('g.sprotty-edge.ecore-edge.composition text.edge-name.sprotty-label').withText('containment'), + referenceEdge: Selector('g.sprotty-edge.ecore-edge text.edge-name.sprotty-label').withText('reference') +}; - async createEdge(name, a, b) { - const selector = Selector('div.tool-group > div.tool-button').withText(name); - await this.t.click(selector).click(a).hover(b).click(b); - } +const attributeSelector = { + attributeClass: Selector('g.node.ecore-node text.sprotty-label').withText('ClassAttribute : EString'), + attributeAbstract: Selector('g.node.ecore-node text.sprotty-label').withText('AbstractAttribute : EString'), + attributeInterface: Selector('g.node.ecore-node text.sprotty-label').withText('InterfaceAttribute : EString'), + literalEnum: Selector('g.node.ecore-node text.sprotty-label').withText('EnumLiteral'), +} - async layout() { - await this.t.pressKey('alt+l').wait(500); - } - async createAllEdges() { - await this.layout(); - await this.createEdge('Reference', this.nodesSelector.classNode, this.nodesSelector.abstractNode); - await this.createEdge('Inheritance', this.nodesSelector.interfaceNode, this.nodesSelector.abstractNode); - await this.createEdge('Containment', this.nodesSelector.interfaceNode, this.nodesSelector.classNode); - } +const defaultNodesSelector = { + classNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('NewEClass0'), + abstractNode: Selector('g.node.ecore-node.abstract text.name.sprotty-label').withText('NewEClass1'), + interfaceNode: Selector('g.node.ecore-node.interface text.name.sprotty-label').withText('NewEClass2'), + enumNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('NewEEnum3'), + dataTypeNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('NewEDataType4') +}; - async deleteAllNodes(t) { - await t - .click(this.nodesSelector.classNode) - .pressKey('delete') - .click(this.nodesSelector.abstractNode) - .pressKey('delete') - .click(this.nodesSelector.enumNode) - .pressKey('delete') - .click(this.nodesSelector.interfaceNode) - .pressKey('delete'); - } +const defaultEdgeSelector = { + inheritanceEdge: Selector('g.sprotty-edge.ecore-edge.inheritance'), + containmentEdge: Selector('g.sprotty-edge.ecore-edge.composition text.edge-name.sprotty-label').withText('classs'), + referenceEdge: Selector('g.sprotty-edge.ecore-edge text.edge-name.sprotty-label').withText('abstracts') +}; - async addAttributes() { - const attribute = Selector('div.tool-group > div.tool-button').withText("Attribute"); - const literal = Selector('div.tool-group > div.tool-button').withText("Literal"); - - this.layout(); - - await this.t - .click(attribute) - .click(this.nodesSelector.classNode) - .click(attribute) - .click(this.nodesSelector.abstractNode) - .click(attribute) - .click(this.nodesSelector.interfaceNode) - .click(literal) - .click(this.nodesSelector.enumNode); - } +const defaultAttributeSelector = { + attributeClass: Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute4 : EString'), + attributeAbstract: Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute5 : EString'), + attributeInterface: Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute6 : EString'), + literalEnum: Selector('g.node.ecore-node text.sprotty-label').withText('NewEEnumLiteral7'), +} - public nodesSelector = { - classNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('NewEClass0'), - abstractNode: Selector('g.node.ecore-node.abstract text.name.sprotty-label').withText('NewEClass1'), - enumNode: Selector('g.node.ecore-node text.name.sprotty-label').withText('NewEEnum2'), - interfaceNode: Selector('g.node.ecore-node.interface text.name.sprotty-label').withText('NewEClass3') - }; - - public edgeSelector = { - inheritanceEdge: Selector('g.sprotty-edge.ecore-edge.inheritance'), - containmentEdge: Selector('g.sprotty-edge.ecore-edge.composition text.edge-name.sprotty-label').withText('neweclass0s'), - referenceEdge: Selector('g.sprotty-edge.ecore-edge text.edge-name.sprotty-label').withText('neweclass1s') - }; - - async getEdgePosition(s: Selector) { - const x = await (s.getAttribute('cx')); - const y = await (s.getAttribute('cy')); - return { x: parseFloat(x), y: parseFloat(y) }; - } +const openFile = async (t, file) => { + await t + .click(selectors.wsSelect) + .click(file); +} - async getNodePosition(s: Selector) { - const transform = await (s.parent("g.node.ecore-node").getAttribute('transform')); - const regex = new RegExp("\\s*\\w*\\s*\\(\\s*(\\d+(\\.\\d+)?)\\s*,\\s*(\\d+(\\.\\d+)?)\\s*\\)\\s*"); - const match = regex.exec(transform); - if (match) { - return { x: parseFloat(match[1]), y: parseFloat(match[3]) }; - } - return {}; - } +const fileSelect = async (file) => { + return Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText(file); } const checkDefaultWorkbench = async (t) => { - const emptyEcore = Helper.emptyEcore(); - const glspGraphEcore = Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('glsp-graph.ecore'); - const glspGraphEnotation = Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('glsp-graph.enotation'); - const umlEcore = Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('UML.ecore'); await t - .expect(emptyEcore.exists).ok('Check if empty.ecore exists') - .expect(glspGraphEcore.exists).ok('Check if glsp-graph.ecore exists') - .expect(glspGraphEnotation.exists).ok('Check if glsp-graph.enotation exists') - .expect(umlEcore.exists).ok('Check if UML.ecore exists') - .expect(Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').count).eql(4); + .expect(selectors.emptyEcore.exists).ok('Check if empty.ecore exists') + .expect(selectors.testEcore.exists).ok('Check if test.ecore exists') + .expect(selectors.testEnotation.exists).ok('Check if test.enotation exists') + .expect(selectors.testNodesOnlyEcore.exists).ok('Check if testNodesOnly.ecore exists') + .expect(selectors.testNodesOnlyEnotation.exists).ok('Check if testNodesOnly.enotation exists') + .expect(selectors.testNodesWithAttributesEcore.exists).ok('Check if testNodesWithAttributes.ecore exists') + .expect(selectors.testNodesWithAttributesEnotation.exists).ok('Check if testNodesWith Attributes.enotation exists') + .expect(selectors.umlEcore.exists).ok('Check if UML.ecore exists') + .expect(Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').count).eql(8); }; const openQuickAccessBar = async (t) => { @@ -181,19 +124,56 @@ const writeQuickAccessBar = async (t, text) => { .pressKey('Enter'); }; +const createNode = async (t, name) => { + const selector = Selector('div.tool-group > div.tool-button').withText(name); + const svgCanvas = Selector('svg.sprotty-graph'); + await t + .click(selector) + .click(svgCanvas); +}; + +const deleteNode = async (t, selector) => { + await t.click(selector).pressKey('delete'); +}; + +const createEdge = async (t, name, a, b) => { + const selector = Selector('div.tool-group > div.tool-button').withText(name); + await t.click(selector).click(a).hover(b).click(b); +}; + +const getNodePosition = async (s: Selector) => { + const transform = await (s.parent("g.node.ecore-node").getAttribute('transform')); + const regex = new RegExp("\\s*\\w*\\s*\\(\\s*(\\d+(\\.\\d+)?)\\s*,\\s*(\\d+(\\.\\d+)?)\\s*\\)\\s*"); + const match = regex.exec(transform); + if (match) { + return { x: parseFloat(match[1]), y: parseFloat(match[3]) }; + } + return {}; +}; + +const getEdgePosition = async (s: Selector) => { + const x = await (s.getAttribute('cx')); + const y = await (s.getAttribute('cy')); + return { x: parseFloat(x), y: parseFloat(y) }; +}; + +const layout = async (t) => { + await t + .pressKey('alt+l') + .wait(500); +}; + const port = process.env.PORT || config.defaultPort; fixture`Ecore-glsp E2E-Testing`// declare the fixture .page`http://localhost:${port}/#${relPathToWorkspace}` - .beforeEach(async t => { - await Helper.load(t); + .after(async t => { }); // The start page loads the workbench at the above defined Path test('Open Workbench', async t => { - const workspace = Helper.wsSelect(); await t .wait(5000) - .click(workspace); + .click(selectors.wsSelect); await checkDefaultWorkbench(t); }); @@ -214,67 +194,45 @@ test('Switch Theme', async t => { .expect(Selector('div.p-Widget.p-DockPanel.p-SplitPanel-child').getStyleProperty('color')).eql('rgb(97, 97, 97)'); }); -test('Open graph-glsp.ecore', async t => { - const wsSelect = Helper.wsSelect(); - const fileSelect = Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('glsp-graph.ecore'); +test('Open UML.ecore (Autolayout/ Big Ecore)', async t => { + openFile(t, selectors.umlEcore); await t - .click(wsSelect) - .click(fileSelect) - .expect(Selector('text.name.sprotty-label').withText('GSeverity').exists).ok('Class GSeverity exists') - .expect(Selector('text.name.sprotty-label').count).eql(50); + .wait(10000) // Necessary to wait as the layouting needs to be executed. + .expect(Selector('text.name.sprotty-label').withText('ConnectorKind').exists).ok('Class ConnectorKind exists') + .expect(Selector('text.name.sprotty-label').count).eql(512) + .expect(Selector('text.name.sprotty-label').withText('ConnectorKind').parent("g.node.ecore-node").getAttribute('transform')).eql('translate(12, 12)'); }); test('Deletion/Renaming of enotation', async t => { - const wsSelect = Helper.wsSelect(); - const fileSelect = Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('glsp-graph.enotation'); - const duplicateFile = Selector('.p-Menu-itemLabel').withText('Duplicate'); - const deleteFile = Selector('.p-Menu-itemLabel').withText('Delete'); - const renameFile = Selector('.p-Menu-itemLabel').withText('Rename'); - const okButton = Selector('.theia-button.main').withText('OK'); - const duplicateFileSelect = Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('glsp-graph_copy.enotation'); - const renameInput = Selector('div.dialogContent > input'); - await t - .click(wsSelect) - .rightClick(fileSelect) - .click(duplicateFile) + .click(selectors.wsSelect) + .rightClick(selectors.testEnotation) + .click(selectors.duplicateFile) .wait(200) - .rightClick(fileSelect) - .click(deleteFile) - .click(okButton) - .expect(Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').count).eql(4) - - .rightClick(duplicateFileSelect) - .click(renameFile) + .rightClick(selectors.testEnotation) + .click(selectors.deleteFile) + .click(selectors.okButton) + .expect(Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').count).eql(8) + .rightClick(await fileSelect('test_copy.enotation')) + .click(selectors.renameFile) .pressKey('ctrl+a') - .typeText(renameInput, "glsp-graph.enotation") + .typeText(selectors.renameInput, "test.enotation") .pressKey('Enter'); }).after(checkDefaultWorkbench); -test('Open Ecore without enotation', async t => { - const wsSelect = Helper.wsSelect(); - const fileSelect = Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('UML.ecore'); - const classSelect = Selector("text.name.sprotty-label").withText("ConnectorKind").parent("g.node.ecore-node"); - - await t - .click(wsSelect) - .click(fileSelect).wait(10000) // Necessary to wait as the layouting needs to be executed. - .expect(classSelect.getAttribute('transform')).notEql('translate(0, 0)'); -}); - test('Create and Delete ecore file', async t => { - const wsSelect = Helper.wsSelect(); + const wsSelect = Selector('#shell-tab-explorer-view-container'); const deleteFile = Selector('.p-Menu-itemLabel').withText('Delete'); const okButton = Selector('.theia-button.main').withText('OK'); - const newEcore = Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('Test.ecore'); + const newEcore = Selector('div.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('Creation.ecore'); openQuickAccessBar(t); writeQuickAccessBar(t, "New Ecore-File"); - writeQuickAccessBar(t, "Test"); - writeQuickAccessBar(t, "testPrefix"); - writeQuickAccessBar(t, "testURI"); + writeQuickAccessBar(t, "Creation"); + writeQuickAccessBar(t, "creationPrefix"); + writeQuickAccessBar(t, "creationURI"); await t .click(wsSelect) @@ -288,244 +246,198 @@ test('Create and Delete ecore file', async t => { }).after(checkDefaultWorkbench); test('Create Nodes', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.layout(); + openFile(t, selectors.emptyEcore); + + createNode(t, "Class"); + createNode(t, "Abstract"); + createNode(t, "Interface"); + createNode(t, "Enum"); + createNode(t, "DataType"); + + layout(t); await t - .expect(creator.nodesSelector.classNode.exists).ok("Class has been created") - .expect(creator.nodesSelector.abstractNode.exists).ok("Abstract has been created") - .expect(creator.nodesSelector.enumNode.exists).ok("Enum has been created") - .expect(creator.nodesSelector.interfaceNode.exists).ok("Interface has been created") + .expect(defaultNodesSelector.classNode.exists).ok("Class has been created") + .expect(defaultNodesSelector.abstractNode.exists).ok("Abstract has been created") + .expect(defaultNodesSelector.interfaceNode.exists).ok("Interface has been created") + .expect(defaultNodesSelector.enumNode.exists).ok("Enum has been created") + .expect(defaultNodesSelector.dataTypeNode.exists).ok("DataType has been created") .pressKey('ctrl+s'); // Check Serialization - const fileSelect = Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('empty.enotation'); - const emptyFile = Selector('.theia-TreeNodeSegment.theia-TreeNodeSegmentGrow').withText('empty.ecore'); - const openWith = Selector('.p-Menu-itemLabel').withText('Open With'); - const codeEditor = Selector('.p-Menu-itemLabel').withText('Code Editor'); - const line = Selector('.view-lines'); // Enotation await t - .click(fileSelect) - .expect(line.child().child().withText('NewEClass0').exists).ok('Enotation serialization worked'); + .click(await fileSelect('empty.enotation')) + .expect(selectors.line.child().child().withText('NewEClass0').exists).ok('Enotation serialization worked') + .expect(selectors.line.child().child().withText('NewEClass1').exists).ok('Enotation serialization worked') + .expect(selectors.line.child().child().withText('NewEClass2').exists).ok('Enotation serialization worked') + .expect(selectors.line.child().child().withText('NewEEnum3').exists).ok('Enotation serialization worked') + .expect(selectors.line.child().child().withText('NewEDataType4').exists).ok('Enotation serialization worked'); // Ecore await t - .rightClick(emptyFile) - .hover(openWith) - .click(codeEditor) - .click(emptyFile) - .expect(line.child().child().withText('NewEClass0').exists).ok('Ecore serialization worked'); + .rightClick(selectors.emptyEcore) + .hover(selectors.openWith) + .click(selectors.codeEditor) + .click(selectors.emptyEcore) + .expect(selectors.line.child().child().withText('NewEClass0').exists).ok('Ecore serialization worked') + .expect(selectors.line.child().child().withText('NewEClass1').exists).ok('Ecore serialization worked') + .expect(selectors.line.child().child().withText('NewEClass2').exists).ok('Ecore serialization worked') + .expect(selectors.line.child().child().withText('NewEEnum3').exists).ok('Ecore serialization worked') + .expect(selectors.line.child().child().withText('NewEDataType4').exists).ok('Ecore serialization worked'); // Delete again - const deleteFile = Selector('.p-Menu-itemLabel').withText('Delete'); - const okButton = Selector('.theia-button.main').withText('OK'); - creator.deleteAllNodes(t); + await t.wait(500); + deleteNode(t, defaultNodesSelector.classNode); + await t.wait(500); + deleteNode(t, defaultNodesSelector.abstractNode); + await t.wait(500); + deleteNode(t, defaultNodesSelector.interfaceNode); + await t.wait(500); + deleteNode(t, defaultNodesSelector.enumNode); + await t.wait(500); + deleteNode(t, defaultNodesSelector.dataTypeNode); + await t.wait(500); await t .pressKey('ctrl+s') - .rightClick(fileSelect) - .click(deleteFile) - .click(okButton); + .rightClick(await fileSelect('empty.enotation')) + .click(selectors.deleteFile) + .click(selectors.okButton); }).after(checkDefaultWorkbench); -// Could check for Serialization -test('Move Class', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.layout(); - const drag_distance = 100; - const original_pos = await creator.getNodePosition(creator.nodesSelector.classNode); - await t - .drag(creator.nodesSelector.classNode, drag_distance, drag_distance, { speed: 0.1 }); - const new_pos = await creator.getNodePosition(creator.nodesSelector.classNode); - await t - .expect(original_pos.x + drag_distance).eql(new_pos.x) - .expect(original_pos.y + drag_distance).eql(new_pos.y); -}); +test('Create Edges', async t => { + openFile(t, selectors.testNodesOnlyEcore); -test('Delete Nodes with Eraser', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - const eraser = Selector('.fas.fa-eraser.fa-xs'); - await creator.layout(); - await t - .click(eraser) - .click(creator.nodesSelector.classNode) - .click(eraser) - .click(creator.nodesSelector.abstractNode) - .click(eraser) - .click(creator.nodesSelector.enumNode) - .click(eraser) - .click(creator.nodesSelector.interfaceNode) - .expect(creator.nodesSelector.classNode.exists).notOk("Class has been deleted") - .expect(creator.nodesSelector.abstractNode.exists).notOk("Abstract has been deleted") - .expect(creator.nodesSelector.enumNode.exists).notOk("Enum has been deleted") - .expect(creator.nodesSelector.interfaceNode.exists).notOk("Interface has been deleted"); -}); + createEdge(t, 'Reference', nodesSelector.classNode, nodesSelector.abstractNode); + createEdge(t, 'Inheritance', nodesSelector.interfaceNode, nodesSelector.abstractNode); + createEdge(t, 'Containment', nodesSelector.interfaceNode, nodesSelector.classNode); -test('Delete Nodes with DEL', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.layout(); - await creator.deleteAllNodes(t); await t - .expect(creator.nodesSelector.classNode.exists).notOk("Class has been deleted") - .expect(creator.nodesSelector.abstractNode.exists).notOk("Abstract has been deleted") - .expect(creator.nodesSelector.enumNode.exists).notOk("Enum has been deleted") - .expect(creator.nodesSelector.interfaceNode.exists).notOk("Interface has been deleted"); + .expect(defaultEdgeSelector.referenceEdge.exists).ok('Reference exists') + .expect(defaultEdgeSelector.containmentEdge.exists).ok('Containment exists') + .expect(defaultEdgeSelector.inheritanceEdge.exists).ok('Inheritance exists'); }); -test('Create Edges', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); +test('Add Attributes/Literals', async t => { + openFile(t, selectors.testNodesOnlyEcore); - await creator.createAllEdges(); + await t + .click(selectors.attribute) + .click(nodesSelector.classNode) + .click(selectors.attribute) + .click(nodesSelector.abstractNode) + .click(selectors.attribute) + .click(nodesSelector.interfaceNode) + .click(selectors.literal) + .click(nodesSelector.enumNode); - await t.expect(creator.edgeSelector.referenceEdge.exists).ok('Reference exists'); - await t.expect(creator.edgeSelector.containmentEdge.exists).ok('Containment exists'); - await t.expect(creator.edgeSelector.inheritanceEdge.exists).ok('Inheritance exists'); + await t + .expect(defaultAttributeSelector.attributeClass.exists).ok("Adding Attribute to Class") + .expect(defaultAttributeSelector.attributeAbstract.exists).ok("Adding Attribute to Abstract") + .expect(defaultAttributeSelector.attributeInterface.exists).ok("Adding Attribute to Interface") + .expect(defaultAttributeSelector.literalEnum.exists).ok("Adding Literal to Enum"); }); -test('Move Edges', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.createAllEdges(); - await creator.layout(); +test('Layout new Diagram', async t => { + openFile(t, selectors.emptyEcore); + createNode(t, "Class"); + createNode(t, "Abstract"); + createNode(t, "Interface"); + createNode(t, "Enum"); - const points = Selector('.sprotty-edge.ecore-edge.selected').child().withAttribute('data-kind', 'manhattan-50%'); - const svgCanvas = Selector('svg.sprotty-graph'); + layout(t); await t - .click(creator.edgeSelector.referenceEdge); - - const original_pos1 = await creator.getEdgePosition(points.nth(0)); - const original_pos2 = await creator.getEdgePosition(points.nth(1)); - const original_pos3 = await creator.getEdgePosition(points.nth(2)); - - await t - .drag(points.nth(0), -10, 0, { speed: 0.1 }) - .click(svgCanvas) - .click(creator.edgeSelector.referenceEdge) - .drag(points.nth(1), 0, -10, { speed: 0.1 }) - .click(svgCanvas) - .click(creator.edgeSelector.referenceEdge) - .drag(points.nth(2), 10, 0, { speed: 0.1 }) - .click(svgCanvas) - .click(creator.edgeSelector.referenceEdge); - - const new_pos1 = await creator.getEdgePosition(points.nth(0)); - const new_pos2 = await creator.getEdgePosition(points.nth(1)); - const new_pos3 = await creator.getEdgePosition(points.nth(2)); + .expect(defaultNodesSelector.classNode.parent("g.node.ecore-node").getAttribute('transform')).eql('translate(12, 12)') + .expect(defaultNodesSelector.enumNode.parent("g.node.ecore-node").getAttribute('transform')).notEql('translate(12, 12)') + .expect(defaultNodesSelector.interfaceNode.parent("g.node.ecore-node").getAttribute('transform')).notEql('translate(12, 12)') + .expect(defaultNodesSelector.abstractNode.parent("g.node.ecore-node").getAttribute('transform')).notEql('translate(12, 12)'); +}); +test('Move Class', async t => { + openFile(t, selectors.testEcore); + await t.wait(500); + const drag_distance = 100; + const original_pos = await getNodePosition(nodesSelector.classNode); await t - .expect(original_pos1.x - 10).eql(new_pos1.x) - .expect(original_pos1.y).eql(new_pos1.y) - .expect(original_pos2.y - 10).eql(new_pos2.y) - .expect(original_pos3.x + 10).eql(new_pos3.x); -}); -test('Delete Edges', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.createAllEdges(); - const eraser = Selector('.fas.fa-eraser.fa-xs'); - await creator.layout(); + .drag(nodesSelector.classNode, drag_distance, drag_distance, { speed: 0.1 }); + const new_pos = await getNodePosition(nodesSelector.classNode); await t - .click(eraser) - .click(creator.edgeSelector.referenceEdge) - .click(eraser) - .click(creator.edgeSelector.containmentEdge) - .click(eraser) - .click(creator.edgeSelector.inheritanceEdge); - await t.expect(creator.edgeSelector.referenceEdge.exists).notOk('Reference deleted'); - await t.expect(creator.edgeSelector.containmentEdge.exists).notOk('Containment deleted'); - await t.expect(creator.edgeSelector.inheritanceEdge.exists).notOk('Inheritance deleted'); + .expect(original_pos.x + drag_distance).eql(new_pos.x) + .expect(original_pos.y + drag_distance).eql(new_pos.y); }); -test('Delete Edges with DEL', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.createAllEdges(); - await creator.layout(); +test('Move Edges', async t => { + openFile(t, selectors.testEcore); + await t - .click(creator.edgeSelector.referenceEdge) - .pressKey('delete') - .click(creator.edgeSelector.containmentEdge) - .pressKey('delete') - .click(creator.edgeSelector.inheritanceEdge) - .pressKey('delete'); - await t.expect(creator.edgeSelector.referenceEdge.exists).notOk('Reference deleted'); - await t.expect(creator.edgeSelector.containmentEdge.exists).notOk('Containment deleted'); - await t.expect(creator.edgeSelector.inheritanceEdge.exists).notOk('Inheritance deleted'); -}); + .click(edgeSelector.referenceEdge); -test('Add Attributes/Literals', async t => { - const creator = new CreateHelper(t); - const attributeClass = Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute4 : EString'); - const attributeAbstract = Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute5 : EString'); - const attributeInterface = Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute6 : EString'); - const attributeEnum = Selector('g.node.ecore-node text.sprotty-label').withText('NewEEnumLiteral7'); + const original_pos1 = await getEdgePosition(selectors.edgePoints.nth(0)); + const original_pos2 = await getEdgePosition(selectors.edgePoints.nth(1)); + const original_pos3 = await getEdgePosition(selectors.edgePoints.nth(2)); - await creator.createAllNodeTypes(); - await creator.addAttributes(); + await t + .drag(selectors.edgePoints.nth(0), 0, -5, { speed: 0.1 }) + .click(selectors.svgCanvas) + .click(edgeSelector.referenceEdge) + .drag(selectors.edgePoints.nth(1), -10, 0, { speed: 0.1 }) + .click(selectors.svgCanvas) + .click(edgeSelector.referenceEdge) + .drag(selectors.edgePoints.nth(2), 0, 5, { speed: 0.1 }) + .click(selectors.svgCanvas) + .click(edgeSelector.referenceEdge); + + const new_pos1 = await getEdgePosition(selectors.edgePoints.nth(0)); + const new_pos2 = await getEdgePosition(selectors.edgePoints.nth(1)); + const new_pos3 = await getEdgePosition(selectors.edgePoints.nth(2)); await t - .expect(attributeClass.exists).ok("Adding Attribute to Class") - .expect(attributeAbstract.exists).ok("Adding Attribute to Abstract") - .expect(attributeInterface.exists).ok("Adding Attribute to Interface") - .expect(attributeEnum.exists).ok("Adding Literal to Enum"); + .expect(original_pos1.y).notEql(new_pos1.y) + .expect(original_pos2.x).notEql(new_pos2.x) + .expect(original_pos3.y).notEql(new_pos3.y); }); -// Could check for Serialization test('Renaming Classes/Attributes', async t => { - const creator = new CreateHelper(t); - const nameClass = creator.nodesSelector.classNode; - const nameAbstract = creator.nodesSelector.abstractNode; - const nameInterface = creator.nodesSelector.interfaceNode; - const nameEnum = creator.nodesSelector.enumNode; - const attributeClass = Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute4 : EString'); - const attributeAbstract = Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute5 : EString'); - const attributeInterface = Selector('g.node.ecore-node text.sprotty-label').withText('NewEAttribute6 : EString'); - const attributeEnum = Selector('g.node.ecore-node text.sprotty-label').withText('NewEEnumLiteral7'); + const attributeClassRenamed = Selector('g.node.ecore-node text.sprotty-label').withText('TestAttributeClass : EString'); const attributeAbstractRenamed = Selector('g.node.ecore-node text.sprotty-label').withText('TestAttributeAbstract : EString'); const attributeInterfaceRenamed = Selector('g.node.ecore-node text.sprotty-label').withText('TestAttributeInterface : EString'); const attributeEnumRenamed = Selector('g.node.ecore-node text.sprotty-label').withText('TestLiteralEnum'); + const nameClassRenamed = Selector('g.node.ecore-node text.name.sprotty-label').withText('TestClass'); const nameAbstractRenamed = Selector('g.node.ecore-node text.name.sprotty-label').withText('TestAbstract'); const nameInterfaceRenamed = Selector('g.node.ecore-node text.name.sprotty-label').withText('TestInterface'); const nameEnumRenamed = Selector('g.node.ecore-node text.name.sprotty-label').withText('TestEnum'); - const input = Selector('div.label-edit input'); - await creator.createAllNodeTypes(); - await creator.addAttributes(); + openFile(t, selectors.testNodesWithAttributesEcore); await t - .doubleClick(nameClass) - .typeText(input, "TestClass") - .click(nameAbstract) - .doubleClick(nameAbstract) - .typeText(input, "TestAbstract") - .click(nameInterface) - .doubleClick(nameInterface) - .typeText(input, "TestInterface") - .click(nameEnum) - .doubleClick(nameEnum) - .typeText(input, "TestEnum") - .click(attributeClass) - .doubleClick(attributeClass) - .typeText(input, "TestAttributeClass") - .click(attributeAbstract) - .doubleClick(attributeAbstract) - .typeText(input, "TestAttributeAbstract") - .click(attributeInterface) - .doubleClick(attributeInterface) - .typeText(input, "TestAttributeInterface") - .click(attributeEnum) - .doubleClick(attributeEnum) - .typeText(input, "TestLiteralEnum") + .doubleClick(nodesSelector.classNode) + .typeText(selectors.input, "TestClass") + .click(nodesSelector.abstractNode) + .doubleClick(nodesSelector.abstractNode) + .typeText(selectors.input, "TestAbstract") + .click(nodesSelector.interfaceNode) + .doubleClick(nodesSelector.interfaceNode) + .typeText(selectors.input, "TestInterface") + .click(nodesSelector.enumNode) + .doubleClick(nodesSelector.enumNode) + .typeText(selectors.input, "TestEnum") + .click(attributeSelector.attributeClass) + .doubleClick(attributeSelector.attributeClass) + .typeText(selectors.input, "TestAttributeClass") + .click(attributeSelector.attributeAbstract) + .doubleClick(attributeSelector.attributeAbstract) + .typeText(selectors.input, "TestAttributeAbstract") + .click(attributeSelector.attributeInterface) + .doubleClick(attributeSelector.attributeInterface) + .typeText(selectors.input, "TestAttributeInterface") + .click(attributeSelector.literalEnum) + .doubleClick(attributeSelector.literalEnum) + .typeText(selectors.input, "TestLiteralEnum") .click(nameClassRenamed) .expect(nameClassRenamed.exists).ok("Renamed Class") .expect(nameAbstractRenamed.exists).ok("Renamed Abstract") @@ -537,39 +449,88 @@ test('Renaming Classes/Attributes', async t => { .expect(attributeEnumRenamed.exists).ok("Renamed Literal in Enum"); }); -// Could check for Serialization test('Change Attributetype', async t => { - const wsSelect = Helper.wsSelect(); - const glspEcore = Helper.glspGraphEcore(); - const attributeSelector = Selector('g.node.ecore-node text.sprotty-label').withText('layout : EString'); + openFile(t, selectors.testNodesWithAttributesEcore) const changedAttribute = Selector('g.node.ecore-node text.sprotty-label').withText('test : EDate'); const changedAttributeWrite = Selector('g.node.ecore-node text.sprotty-label').withText('layout : EString'); - const input = Selector('div.label-edit input'); await t - .click(wsSelect) - .click(glspEcore) - .click(attributeSelector) - .doubleClick(attributeSelector) - .typeText(input, 'test : EDa') + .click(attributeSelector.attributeClass) + .doubleClick(attributeSelector.attributeClass) + .typeText(selectors.input, 'test : EDa') .pressKey('ctrl+space') .pressKey('down') .pressKey('Enter') .expect(changedAttribute.exists).ok("Changing the attributetype via Autocompletion") .doubleClick(changedAttribute) - .typeText(input, 'layout : EString') + .typeText(selectors.input, 'layout : EString') .pressKey('Enter') .expect(changedAttributeWrite.exists).ok("Changing the attributetype via Typing"); }); -test('Style new Diagram', async t => { - const creator = new CreateHelper(t); - await creator.createAllNodeTypes(); - await creator.createAllEdges(); +test('Delete Nodes with Eraser', async t => { + openFile(t, selectors.testEcore); + await t + .click(selectors.eraser) + .click(nodesSelector.classNode, { offsetY: -40 }) + .click(selectors.eraser) + .click(nodesSelector.abstractNode, { offsetY: -40 }) + .click(selectors.eraser) + .click(nodesSelector.enumNode, { offsetY: -40 }) + .click(selectors.eraser) + .click(nodesSelector.interfaceNode, { offsetY: -40 }) + .expect(nodesSelector.classNode.exists).notOk("Class has been deleted") + .expect(nodesSelector.abstractNode.exists).notOk("Abstract has been deleted") + .expect(nodesSelector.enumNode.exists).notOk("Enum has been deleted") + .expect(nodesSelector.interfaceNode.exists).notOk("Interface has been deleted"); +}); - await t.pressKey('alt+l').wait(500) - .expect(creator.nodesSelector.enumNode.parent("g.node.ecore-node").getAttribute('transform')).eql('translate(12, 12)') - .expect(creator.nodesSelector.classNode.parent("g.node.ecore-node").getAttribute('transform')).notEql('translate(12, 12)') - .expect(creator.nodesSelector.interfaceNode.parent("g.node.ecore-node").getAttribute('transform')).notEql('translate(12, 12)') - .expect(creator.nodesSelector.abstractNode.parent("g.node.ecore-node").getAttribute('transform')).notEql('translate(12, 12)'); +test('Delete Nodes with DEL', async t => { + openFile(t, selectors.testEcore); + await t + .wait(200) + .click(nodesSelector.classNode, { offsetY: -40 }) + .pressKey('delete') + .wait(200) + .click(nodesSelector.abstractNode, { offsetY: -40 }) + .pressKey('delete') + .wait(200) + .click(nodesSelector.interfaceNode, { offsetY: -40 }) + .pressKey('delete') + .wait(200) + .click(nodesSelector.enumNode, { offsetY: -40 }) + .pressKey('delete') + .wait(200) + .expect(nodesSelector.classNode.exists).notOk("Class has been deleted") + .expect(nodesSelector.abstractNode.exists).notOk("Abstract has been deleted") + .expect(nodesSelector.interfaceNode.exists).notOk("Interface has been deleted") + .expect(nodesSelector.enumNode.exists).notOk("Enum has been deleted"); +}); + +test('Delete Edges', async t => { + openFile(t, selectors.testEcore); + await t + .click(selectors.eraser) + .click(nodesSelector.classNode, { offsetX: 90 }) + .click(selectors.eraser) + .click(nodesSelector.classNode, { offsetY: 60, offsetX: 15 }) + .click(selectors.eraser) + .click(nodesSelector.interfaceNode, { offsetY: -60, offsetX: 28 }) + .expect(edgeSelector.referenceEdge.exists).notOk('Reference deleted') + .expect(edgeSelector.containmentEdge.exists).notOk('Containment deleted') + .expect(edgeSelector.inheritanceEdge.exists).notOk('Inheritance deleted'); +}); + +test('Delete Edges with DEL', async t => { + openFile(t, selectors.testEcore); + await t + .click(edgeSelector.referenceEdge) + .pressKey('delete') + .click(edgeSelector.containmentEdge) + .pressKey('delete') + .click(edgeSelector.inheritanceEdge) + .pressKey('delete') + .expect(edgeSelector.containmentEdge.exists).notOk('Containment deleted') + .expect(edgeSelector.inheritanceEdge.exists).notOk('Inheritance deleted') + .expect(edgeSelector.referenceEdge.exists).notOk('Reference deleted'); }); diff --git a/client/tests/workspace/UML.ecore b/client/tests/workspace/UML.ecore new file mode 100644 index 0000000..a8ca41b --- /dev/null +++ b/client/tests/workspace/UML.ecore @@ -0,0 +1,17470 @@ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + + + + +
+ + + + + +
+ + +
+ + +
+
+ + + + + +
+ + + + + +
+ + +
+ + +
+
+ + + + + +
+
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + +
+ + + +
+ + + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + +
+
+ + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + + + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+
+
+
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + + + + +
+ + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + +
+
+ + + +
+ + + + + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+
+ + + +
+ + + + + +
+ + + + + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+
+ + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+
+ + + +
+ + + + + + +
+ + + + +
+ + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+
+ + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+
+ + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + +
+
+ + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + + + + +
+ + + + +
+ + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + + + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + +
+ + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+
+ + + +
+ + + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + + +
+ + + +
+ + + + + +
+ + + +
+
+ + + +
+ + + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+
+ + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + +
+ + + + + +
+
+ + +
+ + + + +
+
+ + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + + + +
+ + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + + + + +
+ + + +
+ + + + +
+ + + + + +
+ + + +
+ + +
+ + + +
+ + + + + +
+ + + + + + + +
+ + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + + +
+ + + + +
+ + + + + +
+ + + + + +
+ + + + + + +
+ + + + + +
+ + + +
+ + + +
+ + + + + + +
+ + + +
+ + + + +
+ + + + + + + + + +
+ + + + + +
+ + + +
+ + +
+ + + +
+ + + + + +
+ + + + + + + +
+ + + +
+ + + + +
+ + + + diff --git a/client/tests/workspace/empty.ecore b/client/tests/workspace/empty.ecore new file mode 100644 index 0000000..e0c2564 --- /dev/null +++ b/client/tests/workspace/empty.ecore @@ -0,0 +1,2 @@ + + diff --git a/client/tests/workspace/test.ecore b/client/tests/workspace/test.ecore new file mode 100644 index 0000000..5d19dfe --- /dev/null +++ b/client/tests/workspace/test.ecore @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/client/tests/workspace/test.enotation b/client/tests/workspace/test.enotation new file mode 100644 index 0000000..472534d --- /dev/null +++ b/client/tests/workspace/test.enotation @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/tests/workspace/testNodesOnly.ecore b/client/tests/workspace/testNodesOnly.ecore new file mode 100644 index 0000000..acb5e5e --- /dev/null +++ b/client/tests/workspace/testNodesOnly.ecore @@ -0,0 +1,7 @@ + + + + + + + diff --git a/client/tests/workspace/testNodesOnly.enotation b/client/tests/workspace/testNodesOnly.enotation new file mode 100644 index 0000000..27954a3 --- /dev/null +++ b/client/tests/workspace/testNodesOnly.enotation @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/tests/workspace/testNodesWithAttributes.ecore b/client/tests/workspace/testNodesWithAttributes.ecore new file mode 100644 index 0000000..4165ef3 --- /dev/null +++ b/client/tests/workspace/testNodesWithAttributes.ecore @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/client/tests/workspace/testNodesWithAttributes.enotation b/client/tests/workspace/testNodesWithAttributes.enotation new file mode 100644 index 0000000..1fb1291 --- /dev/null +++ b/client/tests/workspace/testNodesWithAttributes.enotation @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + +