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

Fix schemata updates #67

Merged
merged 25 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
dc17d25
Use editor in schema view for drafts
wwerner Oct 20, 2019
493e5e1
[WIP] E2E test for editing schema spec
wwerner Oct 20, 2019
f317b95
Build dependencies manually instead of pulling them from central due …
wwerner Oct 24, 2019
77725fd
Don't rebuild application within container, use the jar created in pr…
wwerner Oct 25, 2019
ccb251c
Copy target/ from build to image creation step
wwerner Oct 25, 2019
84144b9
Merge branch 'master' into feature/57-edit_draft_schemas
wwerner Oct 25, 2019
94c4720
Enable constraints in HSQL
wwerner Oct 25, 2019
231d6e7
Make assertions for context test more strict
wwerner Oct 25, 2019
4678218
Modify context persistence test to actually update instead of re-crea…
wwerner Oct 25, 2019
09d43f2
Switch test back to HSQL
wwerner Oct 25, 2019
4a81e6c
Assert that updates were persisted in object store tests
wwerner Oct 27, 2019
40cd4ff
Enable unique constraints on HSQLDB
wwerner Oct 27, 2019
d910892
Add category to schema unique constraint
wwerner Oct 27, 2019
fab57d6
Add simple update tests
wwerner Oct 27, 2019
21b4cc5
Make tests more clear
wwerner Oct 27, 2019
ae0c386
Switch tests back to HSQL
wwerner Oct 27, 2019
5b82b56
Fix schema version test assertions
wwerner Oct 27, 2019
aee9ffd
Merge master
wwerner Oct 28, 2019
c3dfcd3
Remove duplicate tests now that the underlying symbio issue is resolved
wwerner Oct 28, 2019
459eafc
Revert some irrelevant local changes to be closer to the tests on master
wwerner Oct 28, 2019
211d616
Remove hardcoded persistence IDs to prevent side effects between mult…
wwerner Oct 28, 2019
97c6f71
Update cypress
wwerner Oct 28, 2019
21e99ca
Update tests to support monaco editor
wwerner Oct 28, 2019
b3b0579
Ignore failing test for now, see issue #69
wwerner Oct 28, 2019
47ead2c
Improve edit dialog layout
wwerner Oct 28, 2019
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
19 changes: 18 additions & 1 deletion src/main/frontend/src/api/SchemataRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ const resources = {
categories: () => '/schema/categories',
scopes: () => '/schema/scopes',
schemata: (o, u, c) => `/organizations/${o}/units/${u}/contexts/${c}/schemas`,
versions: (o, u, c, s) => `/organizations/${o}/units/${u}/contexts/${c}/schemas/${s}/versions`
versions: (o, u, c, s) => `/organizations/${o}/units/${u}/contexts/${c}/schemas/${s}/versions`,
schemaSpecification: (o, u, c, s, v) => `/organizations/${o}/units/${u}/contexts/${c}/schemas/${s}/versions/${v}/specification`
}

function ensure(response, status) {
Expand Down Expand Up @@ -128,4 +129,20 @@ export default {
.then(ensureCreated)
.then(response => response.data)
},
saveSchemaVersionSpecification(
organization, unit, context, schema, version, specification) {
let config = {
headers: {
'Content-Type': 'application/json'
},
responseType: 'text'
};
return Repository.patch(
resources.schemaSpecification(organization, unit, context, schema, version),
specification,
config
)
.then(ensureOk)
.then(response => response.data)
},
}
69 changes: 57 additions & 12 deletions src/main/frontend/src/components/Properties.vue
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
<template>
<v-card height="45vh" id="schemata-properties">
<v-card-text>
<v-alert v-if="status && status !== 'Published'" :value="true" type="warning" outlined>
<v-alert v-if="status && status !== 'Published'" :value="true" type="warning" dense outlined>
Status <b>{{status}}</b>. Do not use in production.
</v-alert>
<v-tabs>
<v-tab>Specification</v-tab>
<v-tab>Description</v-tab>

<v-tab-item>
<code>{{ specification }}</code>
<editor
id="specification-editor"
v-model="currentSpecification"
theme="vs-dark"
language="javascript"
height="200"
:options="editorOptions"
></editor>
<br>
<v-btn color="info"
:disabled="status !== 'Draft'"
@click="saveSpecification">Save
</v-btn>
</v-tab-item>

<v-tab-item>
<div v-html="compiledDescription()"></div>
</v-tab-item>
</v-tabs>
</v-card-text>

</v-card>


Expand All @@ -26,14 +37,30 @@
<script>
import {mapFields} from 'vuex-map-fields';
import marked from 'marked'
import editor from 'monaco-editor-vue';
import Repository from '@/api/SchemataRepository'

export default {
components: {editor},
data: function () {
return {
currentSpecification: undefined,
}
},

computed: {
...mapFields([
'schema',
'version'
]),

editorOptions() {
return {
readOnly: this.status !== 'Draft',
automaticLayout: true,
}
},

specification() {
return this.version?.specification ?? ''
},
Expand All @@ -44,22 +71,40 @@
return this.version?.status ?? ''
},
},
watch: {
specification(val) {
this.currentSpecification = val
}
},
methods: {
compiledDescription: function () {
return marked(this.description)
},
saveSpecification: function () {
let vm = this
Repository.saveSchemaVersionSpecification(
this.version.organizationId,
this.version.unitId,
this.version.contextId,
this.version.schemaId,
this.version.schemaVersionId,
this.currentSpecification
)
.then(() => {
vm.$store.commit('raiseNotification', {
message: `Specification for ${vm.schema.name} v${vm.version.currentVersion} updated.`,
type: 'success'
})
}
)
.catch(function (err) {
let response = err.response ? err.response.data + ' - ' : ''
vm.$store.commit('raiseError', {message: response + err})
})
}
}
}
</script>

<style>
.v-card {
overflow-y: auto
}

code {
width: 100%;
font-size: larger;
font-weight: lighter;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ protected void createOrganizationStateTable() {
"organizationId VARCHAR (50) NOT NULL, " +
"name VARCHAR(128) NOT NULL, " +
"description VARCHAR(8000) " +

// "UNIQUE (name) " +
")");

// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS ORG_ALL_INDEX ON TBL_ORGANIZATIONS (organizationId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS ORG_ALL_INDEX ON TBL_ORGANIZATIONS (organizationId)");
jdbi.handle().execute("ALTER TABLE TBL_ORGANIZATIONS ADD CONSTRAINT IF NOT EXISTS ORGANIZATION_UNIQUE UNIQUE (name)");
}

@Override
Expand All @@ -37,12 +36,11 @@ protected void createUnitStateTable() {
"organizationId VARCHAR (50) NOT NULL, " +
"name VARCHAR(128) NOT NULL, " +
"description VARCHAR(8000) " +

// "UNIQUE (organizationId, name) " +
")");

// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS UNIT_PARENT_INDEX ON TBL_UNITS (organizationId)");
// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS UNIT_ALL_INDEX ON TBL_UNITS (organizationId, unitId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS UNIT_PARENT_INDEX ON TBL_UNITS (organizationId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS UNIT_ALL_INDEX ON TBL_UNITS (organizationId, unitId)");
jdbi.handle().execute("ALTER TABLE TBL_UNITS ADD CONSTRAINT IF NOT EXISTS UNIT_ALL_UNIQUE UNIQUE (organizationId, name)");
}

@Override
Expand All @@ -56,12 +54,12 @@ protected void createContextStateTable() {
"organizationId VARCHAR (50) NOT NULL, " +
"namespace VARCHAR(256) NOT NULL, " +
"description VARCHAR(8000) " +

// "UNIQUE (unitId, namespace) " +
")");

// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS CONTEXT_PARENT_INDEX ON TBL_CONTEXTS (organizationId, unitId)");
// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS CONTEXT_ALL_INDEX ON TBL_CONTEXTS (organizationId, unitId, contextId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS CONTEXT_PARENT_INDEX ON TBL_CONTEXTS (organizationId, unitId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS CONTEXT_ALL_INDEX ON TBL_CONTEXTS (organizationId, unitId, contextId)");

jdbi.handle().execute("ALTER TABLE TBL_CONTEXTS ADD CONSTRAINT IF NOT EXISTS CONTEXT_ALL_UNIQUE UNIQUE (organizationId, unitId, namespace)");
}

@Override
Expand All @@ -78,12 +76,11 @@ protected void createSchemaStateTable() {
"scope VARCHAR(25) NOT NULL, " +
"name VARCHAR(128) NOT NULL, " +
"description VARCHAR(8000) " +

// "UNIQUE (contextId, category, name) " +
")");

// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_PARENT_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId)");
// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_ALL_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId, schemaId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_PARENT_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_ALL_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId, schemaId)");
jdbi.handle().execute("ALTER TABLE TBL_SCHEMAS ADD CONSTRAINT IF NOT EXISTS SCHEMA_ALL_UNIQUE UNIQUE (organizationId, unitId, contextId, category, name)");
}

@Override
Expand Down Expand Up @@ -120,8 +117,9 @@ protected void createSchemaVersionStateTable() {
// "UNIQUE (schemaId, currentVersion) " +
")");

// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMAVERSION_PARENT_INDEX ON TBL_SCHEMAVERSIONS (organizationId, unitId, contextId, schemaId)");
// jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMAVERSION_ALL_INDEX ON TBL_SCHEMAVERSIONS (organizationId, unitId, contextId, schemaId, schemaVersionId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMAVERSION_PARENT_INDEX ON TBL_SCHEMAVERSIONS (organizationId, unitId, contextId, schemaId)");
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMAVERSION_ALL_INDEX ON TBL_SCHEMAVERSIONS (organizationId, unitId, contextId, schemaId, schemaVersionId)");
jdbi.handle().execute("ALTER TABLE TBL_SCHEMAVERSIONS ADD CONSTRAINT IF NOT EXISTS SCHEMAVERSIION_ALL_UNIQUE UNIQUE (organizationId, unitId, contextId, schemaId, currentVersion)");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,8 @@ protected void createOrganizationStateTable() {
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS ORG_ALL_INDEX ON TBL_ORGANIZATIONS (organizationId)");

/*
Dropping the constraint and recreating it afterwards is not an optimal solution once we have actual data.

TODO: Refactor to find out if constraint already exists or switch to a schema migration tool like flyway or liquibase
* Dropping the constraint and recreating it afterwards is not an optimal solution once we have actual data.
* TODO: Refactor to find out if constraint already exists or switch to a schema migration tool like flyway or liquibase
*/
jdbi.handle().execute("ALTER TABLE TBL_ORGANIZATIONS DROP CONSTRAINT IF EXISTS ORGANIZATION_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_ORGANIZATIONS ADD CONSTRAINT ORGANIZATION_UNIQUE UNIQUE (name)");
Expand Down Expand Up @@ -96,7 +95,7 @@ protected void createSchemaStateTable() {
jdbi.handle().execute("CREATE UNIQUE INDEX IF NOT EXISTS SCHEMA_ALL_INDEX ON TBL_SCHEMAS (organizationId, unitId, contextId, schemaId)");

jdbi.handle().execute("ALTER TABLE TBL_SCHEMAS DROP CONSTRAINT IF EXISTS SCHEMA_ALL_UNIQUE");
jdbi.handle().execute("ALTER TABLE TBL_SCHEMAS ADD CONSTRAINT SCHEMA_ALL_UNIQUE UNIQUE (organizationId, unitId, contextId, name)");
jdbi.handle().execute("ALTER TABLE TBL_SCHEMAS ADD CONSTRAINT SCHEMA_ALL_UNIQUE UNIQUE (organizationId, unitId, contextId, category, name)");

}

Expand Down
94 changes: 92 additions & 2 deletions src/test/e2e/cypress/integration/browse-schemata.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,101 @@ describe('Schemata View Tests', function () {
cy.contains('.v-list-item__title', currentVersion).click()

// Assert spec & desc
cy.contains('code','event SalutationHappened')
cy.contains('code','type eventType')
cy.editorContent('#specification-editor').should('contain','event SalutationHappened')
cy.editorContent('#specification-editor').should('contain','type eventType')


cy.contains('.v-tab', 'Description').click()
cy.contains('.v-window-item--active',desc)

});

it('can update schema version specification', function () {
// Setup
let orgName = faker.company.companyName()
let unitName = faker.lorem.word()
let namespace = faker.internet.domainName()
let schema = faker.company.catchPhraseNoun()
let majorMinorVersion = faker.random.number(9) + '.' + faker.random.number(9)
let patchVersion = faker.random.number(9)
let prevVersion = majorMinorVersion + '.' + patchVersion
let currentVersion = majorMinorVersion + '.' + (patchVersion + 1)
let spec = 'event SalutationHappened {\n' +
' type eventType'
let desc = faker.lorem.sentence()

// Create Entities
cy.visit('/#/organization')
cy.fillField('Name', orgName)
cy.fillField('Description', 'foo')
cy.contains('button', 'Create').click()
cy.contains('a', 'Create Unit').click()

cy.selectOption('Organization', orgName)
cy.fillField('Name', unitName)
cy.fillField('Description', 'foo')
cy.contains('button', 'Create').click()
cy.contains('a', 'Create Context').click()

cy.selectOption('Organization', orgName)
cy.selectOption('Unit', unitName)
cy.fillField('Namespace', namespace)
cy.fillField('Description', 'foo')
cy.contains('button', 'Create').click()
cy.contains('a', 'Create Schema').click()

cy.fieldContent('SchemaID').should('be.empty')
cy.selectOption('Organization', orgName)
cy.selectOption('Unit', unitName)
cy.selectOption('Context', namespace)
cy.fillField('Name', schema)
cy.selectOption('Category', faker.random.arrayElement(['Command', 'Data', 'Document', 'Envelope', 'Event', 'Unknown']))
cy.selectOption('Scope', faker.random.arrayElement(['Public', 'Private']))
cy.fillField('Description', faker.lorem.sentence())
cy.contains('button', 'Create').click()
cy.contains('a', 'Create Schema Version').click()

cy.fieldContent('SchemaVersionID').should('be.empty')
cy.selectOption('Organization', orgName)
cy.selectOption('Unit', unitName)
cy.selectOption('Context', namespace)
cy.selectOption('Schema', schema)
cy.fillField('Previous Version', prevVersion)
cy.fillField('Current Version', currentVersion)
cy.selectOption('Status', 'Draft')
cy.fillEditor('#description-editor', desc)
cy.fillEditor('#specification-editor', spec)
cy.contains('button', 'Create').click()

// Assert visibility in treeview
// Filter for Org
cy.visit("/#/schemata")
.fillField('Search', orgName)

// Expand Tree
cy.contains('.v-treeview-node__label', orgName).click()
cy.contains('.v-treeview-node__label', unitName).click()
cy.contains('.v-treeview-node__label', namespace).click()
cy.contains('.v-treeview-node__label', schema).click()

// Select version
cy.contains('.v-list-item__title', currentVersion).click()

// Change spec
cy.fillEditor('#specification-editor', 'foo bar baz')
cy.contains('button', 'Save').click()

// Reload and navigate to schema version
cy.reload()
cy.visit("/#/schemata")
.fillField('Search', orgName)
cy.contains('.v-treeview-node__label', orgName).click()
cy.contains('.v-treeview-node__label', unitName).click()
cy.contains('.v-treeview-node__label', namespace).click()
cy.contains('.v-treeview-node__label', schema).click()
cy.contains('.v-list-item__title', currentVersion).click()

cy.editorContent('#specification-editor').should('contain','foo bar baz')
});

});
9 changes: 9 additions & 0 deletions src/test/e2e/cypress/support/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ Cypress.Commands.add("fieldContent", (label: string) => {
.next('input,textarea').invoke('val')
})

Cypress.Commands.add("editorContent", (id: string) => {
cy.get(id)
.get('.monaco-editor .lines-content')
.then(content => content.text()
.replace(/\s+/g, ' ')
.trim()
)
})

Cypress.Commands.add("selectOption", (label: string, optionLabel: string) => {
cy.contains('label', new RegExp("^" + label + "$"))
.next('input')
Expand Down
8 changes: 8 additions & 0 deletions src/test/e2e/cypress/support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ declare namespace Cypress {
*/
fillEditor(label: string, text: string): Chainable<Element>

/**
* Get the contents of a vue-monaco-editor field identified by its id.
* Note that whitespace is simplified, all consecutive whitespaces are reduced to one
* and leading and trailing whitespace is removed.
* @example cy.editorContent('#specification-editor')
*/
editorContent(id: string): Chainable<Element>

/**
* Return the value a Vuetify text(area) field identified by its label
* @example cy.fieldContent('Name')
Expand Down
Loading