Skip to content

Commit

Permalink
fix(editing): reactively update after changes to doc (openscd#814)
Browse files Browse the repository at this point in the history
* fix(editing): reactively update after changes to doc

* test(ValidateTemplates): move integration tests to integration test file

* fix(hosting): prevent error with no editors loaded

This prevents an error that shows up in integration tests which don't
load any editor type plugins.
  • Loading branch information
ca-d authored Jun 8, 2022
1 parent a7af8b2 commit 78e8f0f
Show file tree
Hide file tree
Showing 17 changed files with 278 additions and 265 deletions.
2 changes: 1 addition & 1 deletion public/js/plugins.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const officialPlugins = [
position: 'top'
},
{
name: 'Validate project',
name: 'Validate Schema',
src: '/src/validators/ValidateSchema.js',
icon: 'rule_folder',
default: true,
Expand Down
13 changes: 11 additions & 2 deletions src/Editing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,8 +423,17 @@ export function Editing<TBase extends LitElementConstructor>(Base: TBase) {

this.dispatchEvent(newValidateEvent());

for (const element of event.composedPath())
if (element instanceof LitElement) element.requestUpdate();
if (!this.doc) return;

const newDoc = document.implementation.createDocument(
this.doc.lookupNamespaceURI(''),
this.doc.documentElement.tagName,
this.doc.doctype
);

// change the document object reference to enable reactive updates
newDoc.documentElement.replaceWith(this.doc.documentElement);
this.doc = newDoc;
}

private async onOpenDoc(event: OpenDocEvent) {
Expand Down
2 changes: 1 addition & 1 deletion src/Hosting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ export function Hosting<
</mwc-top-app-bar-fixed>
</mwc-drawer>
${this.doc
${this.doc && this.editors[this.activeTab]?.content
? this.editors[this.activeTab].content
: html`<div class="landing">
${(<MenuItem[]>this.menu.filter(mi => mi !== 'divider')).map(
Expand Down
2 changes: 1 addition & 1 deletion src/Plugging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ export function Plugging<TBase extends new (...args: any[]) => EditingElement>(
private get storedPlugins(): Plugin[] {
return <Plugin[]>(
JSON.parse(localStorage.getItem('plugins') ?? '[]', (key, value) =>
value.src ? this.addContent(value) : value
value.src && value.installed ? this.addContent(value) : value
)
);
}
Expand Down
34 changes: 11 additions & 23 deletions src/validators/ValidateTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,6 @@ import { validateChildren } from './templates/foundation.js';

type ValidationResult = LogDetailBase | LogDetail;

export function dispatch(detail: ValidationResult, validatorId: string): void {
const kind = (<LogDetail>detail).kind;
const title = (<LogDetailBase>detail).title;
const message = (<LogDetailBase>detail).message;

if (kind)
document
.querySelector('open-scd')
?.dispatchEvent(newLogEvent(<LogDetail>detail));
else
document.querySelector('open-scd')?.dispatchEvent(
newIssueEvent({
validatorId,
title,
message,
})
);
}

export default class ValidateTemplates extends LitElement {
@property({ attribute: false })
doc!: XMLDocument;
Expand Down Expand Up @@ -61,12 +42,19 @@ export default class ValidateTemplates extends LitElement {
const data = this.doc.querySelector('DataTypeTemplates');
if (!data) return;

const issuesTemaplte = await validateChildren(data);
if (issuesTemaplte.length === 0)
issuesTemaplte.push({
const templateIssues = await validateChildren(data);
if (templateIssues.length === 0)
templateIssues.push({
title: get('diag.zeroissues'),
});

issuesTemaplte.forEach(error => dispatch(error, this.pluginId));
templateIssues.forEach(error =>
this.dispatchEvent(
newIssueEvent({
...error,
validatorId: this.pluginId,
})
)
);
}
}
2 changes: 1 addition & 1 deletion src/validators/templates/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export async function validateChildren(
const children = Array.from(element.children);

for (const child of children) {
const validator = await tagValidator[child.tagName];
const validator = tagValidator[child.tagName];
if (!validator) continue;

const childIssues = await validator(child);
Expand Down
4 changes: 2 additions & 2 deletions test/integration/__snapshots__/open-scd.test.snap.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ snapshots["open-scd looks like its snapshot"] =
rule_folder
</mwc-icon>
<span>
Validate project
Validate Schema
</span>
<oscd-plugin3aa68346726da1cd>
</oscd-plugin3aa68346726da1cd>
Expand Down Expand Up @@ -774,7 +774,7 @@ snapshots["open-scd looks like its snapshot"] =
<mwc-icon slot="meta">
rule_folder
</mwc-icon>
Validate project
Validate Schema
</mwc-check-list-item>
<mwc-check-list-item
aria-disabled="false"
Expand Down
52 changes: 29 additions & 23 deletions test/integration/editors/cleanup/control-blocks-container.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
await element.cleanButton.click();

// the correct number of LogControls should remain
expect(doc.querySelectorAll('LogControl')).to.have.length(1);
expect(doc.querySelectorAll('LogControl[name="LogNP"]')).to.have.length(
0
);
expect(element.doc.querySelectorAll('LogControl')).to.have.length(1);
expect(
element.doc.querySelectorAll('LogControl[name="LogNP"]')
).to.have.length(0);
});

it('correctly removes all GSEControl entries and Address entries from the SCL', async () => {
Expand All @@ -77,15 +77,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
await element.cleanButton.click();

// the correct number of GSEControl should remain
expect(doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
expect(element.doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
expect(
doc.querySelectorAll(
element.doc.querySelectorAll(
'GSEControl[name="GCB_NP"], GSEControl[name="GCB2_NP"]'
)
).to.have.lengthOf(0);
// Addresses removed
expect(doc.querySelectorAll('GSE[cbName="GCB_NP"]')).to.have.lengthOf(0);
expect(doc.querySelectorAll('GSE')).to.have.lengthOf(1);
expect(
element.doc.querySelectorAll('GSE[cbName="GCB_NP"]')
).to.have.lengthOf(0);
expect(element.doc.querySelectorAll('GSE')).to.have.lengthOf(1);
});

it('correctly removes all SampledValueControl and Address entries from the SCL', async () => {
Expand All @@ -102,15 +104,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
await element.cleanButton.click();

// the correct number of SampledValueControls should remain
expect(doc.querySelectorAll('SampledValueControl')).to.have.lengthOf(1);
expect(
doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
element.doc.querySelectorAll('SampledValueControl')
).to.have.lengthOf(1);
expect(
element.doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
).to.have.lengthOf(0);
// Addresses removed
expect(doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')).to.have.lengthOf(
0
);
expect(doc.querySelectorAll('SMV')).to.have.lengthOf(1);
expect(
element.doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')
).to.have.lengthOf(0);
expect(element.doc.querySelectorAll('SMV')).to.have.lengthOf(1);
});

describe('if the Address checkbox is unchecked', () => {
Expand All @@ -132,15 +136,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
await element.cleanButton.click();

// the correct number of SampledValueControls should remain
expect(doc.querySelectorAll('SampledValueControl')).to.have.lengthOf(1);
expect(
doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
element.doc.querySelectorAll('SampledValueControl')
).to.have.lengthOf(1);
expect(
element.doc.querySelectorAll('SampledValueControl[name="MSVCB01_A"]')
).to.have.lengthOf(0);
// Addresses unchanged
expect(
doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')
element.doc.querySelectorAll('SMV[cbName="MSVCB01_A"]')
).to.have.lengthOf(1);
expect(doc.querySelectorAll('SMV')).to.have.lengthOf(2);
expect(element.doc.querySelectorAll('SMV')).to.have.lengthOf(2);
});

it('correctly removes all GSEControl entries but not Address entries from the SCL', async () => {
Expand All @@ -160,17 +166,17 @@ describe('cleanup-editor integration: unreferenced control blocks', () => {
await element.cleanButton.click();

// the correct number of GSEControl should remain
expect(doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
expect(element.doc.querySelectorAll('GSEControl')).to.have.lengthOf(2);
expect(
doc.querySelectorAll(
'GSEControl[name="GCB_NP"], GSEControl[name="GCB2_NP"]'
)
).to.have.lengthOf(0);
// Addresses unchanged
expect(doc.querySelectorAll('GSE[cbName="GCB_NP"]')).to.have.lengthOf(
1
);
expect(doc.querySelectorAll('GSE')).to.have.lengthOf(2);
expect(
element.doc.querySelectorAll('GSE[cbName="GCB_NP"]')
).to.have.lengthOf(1);
expect(element.doc.querySelectorAll('GSE')).to.have.lengthOf(2);
});
});

Expand Down
4 changes: 2 additions & 2 deletions test/integration/editors/cleanup/datasets-container.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,12 +70,12 @@ describe('cleanup-editor integration: dataset removal', () => {
await element.cleanupButton!.click();
// the correct number of DataSets should remain
const remainingDataSetCountCheck =
doc.querySelectorAll(
element.doc.querySelectorAll(
':root > IED > AccessPoint > Server > LDevice > LN0 > DataSet, :root > IED > AccessPoint > Server > LDevice > LN > DataSet'
).length === 6;
// those DataSets selected had best be gone
const datasetsCorrectlyRemoved =
doc.querySelectorAll(
element.doc.querySelectorAll(
'DataSet[name="GooseDataSet2"], DataSet[name="PhsMeas2"]'
).length === 0;
expect(remainingDataSetCountCheck && datasetsCorrectlyRemoved).to.equal(
Expand Down
Loading

0 comments on commit 78e8f0f

Please sign in to comment.