Implement JSON formatting and syntax highlighting#443
Implement JSON formatting and syntax highlighting#443AmerMesanovic wants to merge 2 commits intoastarte-platform:masterfrom
Conversation
2148e57 to
e493080
Compare
e493080 to
b761066
Compare
b761066 to
896bc9b
Compare
896bc9b to
1d73438
Compare
1d73438 to
db10ac3
Compare
db10ac3 to
339313b
Compare
00f7438 to
a095ea6
Compare
a095ea6 to
2e2ccbe
Compare
2e2ccbe to
44e9eb8
Compare
cypress/e2e/interface_builder.cy.js
Outdated
| databaseTTL, | ||
| } = parseMappingOptions(_.get(iface.mappings, '0')); | ||
| const { reliability, explicitTimestamp, retention, expiry, databaseRetention, databaseTTL } = | ||
| parseMappingOptions(_.get(iface.mappings, '0')); |
There was a problem hiding this comment.
if there are no changes, please avoid to change code format as this will introduce undesired noise to the pr.
Same goes for unnecessary ; at the end of a line
there are multiple occurrences in this PR that only changes how the code is styled but add nothing, it's better to move a restyling in another PR
cypress/e2e/interface_builder.cy.js
Outdated
| .within(() => { | ||
| cy.contains(mapping.endpoint); | ||
| cy.get('button').contains('Edit...').click(); | ||
| cy.get('button').contains('Edit...').should('have.length', 1).click({ force: true }); |
There was a problem hiding this comment.
we could possible have more that one edit button? There is a necessity to check that?
cypress/e2e/interface_builder.cy.js
Outdated
| cy.fixture(interfaceFixture).then(({ data: iface }) => { | ||
| setupInterfaceEditorFromUI(iface); | ||
| checkInterfaceEditorUIValues(iface); | ||
|
|
There was a problem hiding this comment.
as above, avoid newlines if not necessary
cypress/e2e/trigger_builder.cy.js
Outdated
| if (win.monaco && win.monaco.editor) { | ||
| const editor = win.monaco.editor.getModels()[0]; | ||
| const editorContent = editor.getValue(); | ||
| const editorJson = JSON.parse(editorContent); | ||
|
|
||
| expect(editorJson.simple_triggers[0].interface_name).to.equal(iface); | ||
| } else { | ||
| throw new Error('Monaco Editor instance is not available'); | ||
| } | ||
| }); | ||
| cy.window().then((win) => { | ||
| if (win.monaco && win.monaco.editor) { | ||
| const editor = win.monaco.editor.getModels()[0]; | ||
| const editorContent = editor.getValue(); | ||
| const editorJson = JSON.parse(editorContent); | ||
|
|
||
| expect(editorJson.simple_triggers[0].interface_major).to.equal(simpleTrigger.interface_major); | ||
| } else { | ||
| throw new Error('Monaco Editor instance is not available'); | ||
| } | ||
| }); | ||
| cy.window().then((win) => { | ||
| if (win.monaco && win.monaco.editor) { | ||
| const editor = win.monaco.editor.getModels()[0]; | ||
| const editorContent = editor.getValue(); | ||
| const editorJson = JSON.parse(editorContent); | ||
|
|
||
| expect(editorJson.simple_triggers[0].match_path).to.equal(simpleTrigger.match_path); | ||
| } else { | ||
| throw new Error('Monaco Editor instance is not available'); | ||
| } |
There was a problem hiding this comment.
Here there is a repetition of
cy.window().then((win) => {
if (win.monaco && win.monaco.editor) {
const editor = win.monaco.editor.getModels()[0];
const editorContent = editor.getValue();
const editorJson = JSON.parse(editorContent);
all of that can be merged in a single if clause
cypress/e2e/trigger_builder.cy.js
Outdated
| .scrollIntoView() | ||
| .should('be.visible') | ||
| .contains(simpleTrigger.interface_major) | ||
| .contains(triggerOperatorToLabel[simpleTrigger.value_match_operator]) |
There was a problem hiding this comment.
good to check for more than one property, but
.contains(simpleTrigger.interface_major)
got removed
cypress/e2e/trigger_builder.cy.js
Outdated
| .scrollIntoView() | ||
| .should('be.visible') | ||
| .contains(simpleTrigger.interface_major) | ||
| .contains(triggerOperatorToLabel[simpleTrigger.value_match_operator]) |
There was a problem hiding this comment.
good to check for more than one property, but
.contains(simpleTrigger.interface_major)
got removed entirely
cypress/e2e/trigger_builder.cy.js
Outdated
| cy.get('#triggerSource', { timeout: 1000 }).scrollIntoView().should('be.visible'); | ||
| cy.get('button').contains('Hide source', { timeout: 1000 }).scrollIntoView().click(); | ||
| cy.get('#triggerSource', { timeout: 1000 }).should('not.exist'); | ||
| cy.get('button').contains('Show source', { timeout: 1000 }).scrollIntoView().click(); | ||
| cy.get('#triggerSource', { timeout: 1000 }).scrollIntoView().should('be.visible'); |
There was a problem hiding this comment.
if not required, all of those timeouts would only prolong the duration of this already long tests
This apply for the entire PR, check and be sure the timeouts/cy.wait functions are really needed
Enhance UX in Dashboard with JSON text editor using Monaco Editor (@monaco-editor/react) for improved formatting, syntax highlighting, and validation error reporting. Signed-off-by: AmerMesanovic <amer.mesanovic@secomind.com>
44e9eb8 to
03aa1da
Compare
0c6eadb to
1563051
Compare
82336bc to
2e397f2
Compare
utilizing MonacoEditor. - Updated test selectors to target JSONEditor component. - Used force option for clicks to handle overlays in the editor. - Increased timeouts where necessary to account for MonacoEditor's loading times Signed-off-by: AmerMesanovic <amer.mesanovic@secomind.com>
2e397f2 to
393030d
Compare
eddbbt
left a comment
There was a problem hiding this comment.
@Annopaolo can we relaunch the CI? imho it's just cypress flakiness
| import React, { createContext, useContext, useEffect, useState } from 'react'; | ||
| import monaco from '@monaco-editor/react'; | ||
|
|
||
| interface MonacoContextType { | ||
| monaco: typeof monaco | null; | ||
| } | ||
|
|
||
| const MonacoContext = createContext<MonacoContextType | undefined>(undefined); | ||
|
|
||
| export const MonacoProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { | ||
| const [monacoInstance, setMonacoInstance] = useState<typeof monaco | null>(null); | ||
|
|
||
| useEffect(() => { | ||
| if (!monacoInstance) { | ||
| setMonacoInstance(monaco); | ||
| } | ||
| }, [monacoInstance]); | ||
|
|
||
| return ( | ||
| <MonacoContext.Provider value={{ monaco: monacoInstance }}>{children}</MonacoContext.Provider> | ||
| ); | ||
| }; | ||
|
|
||
| export const useMonacoContext = (): MonacoContextType => { | ||
| const context = useContext(MonacoContext); | ||
| if (!context) { | ||
| throw new Error('useMonacoContext must be used within a MonacoProvider'); | ||
| } | ||
| return context; | ||
| }; |
There was a problem hiding this comment.
This file defines a MonacoContext and a useMonacoContext, but it seems they are not really used anywhere (besides wrapping the App with MonacoProvider).
What is their purpose? Can we get rid of them?
From the documentation of the editor it should be enough to import its React component and render it where needed, as you already did.
| cy.get('.monaco-editor') | ||
| .should('be.visible') | ||
| .then(() => { | ||
| cy.window().then((win) => { | ||
| const editor = win.monaco.editor.getModels()[0]; | ||
| editor.setValue(JSON.stringify(iface, null, 4)); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
It would be ideal to stick to the basic Cypress commands, thus simulating an actual user interacting and writing (or pasting) into the editor.
The main idea when doing e2e tests is to avoid thinking about the implementation and just test the expected user interaction.
Do you think it's feasible, or did you encounter some issues?
| interfaceFixtures.forEach((interfaceFixture) => { | ||
| cy.fixture(interfaceFixture).then(({ data: iface }) => { | ||
| setupInterfaceEditorFromSource(iface); | ||
| setupInterfaceEditorFromUI(iface); |
There was a problem hiding this comment.
This looks like cheating :)
This test correctly loads interface from its source should validate that when the user writes into the editor (setupInterfaceEditorFromSource(iface)) then the UI form fields are automatically updated and correspond to the provided source.
If we call setupInterfaceEditorFromUI(iface) to setup the UI form fields, of course they will correspond: it defies the purpose of the test.
If we want to maintain the same behavior, we can update the implementation instead of the test, making sure that when the user changes the editor's content then the UI fields are updated.
Enhance UX in Dashboard with JSON text editor using Monaco Editor (@monaco-editor/react) for improved formatting, syntax highlighting, and validation error reporting.