From 1a4b359fd13999da9a5f2fc465bb9ced80c6a9bc Mon Sep 17 00:00:00 2001 From: lawson89 Date: Thu, 13 Nov 2025 15:23:25 -0600 Subject: [PATCH 1/4] Transfer previewer code to sierra project --- sierra-previewer/build.gradle | 15 + sierra-previewer/gradle.properties | 0 .../httprpc/sierra/previewer/MainFrame.java | 523 +++++++++++++++++- .../sierra/previewer/RecentFilesManager.java | 108 ++++ .../sierra/previewer/SierraPreviewerApp.java | 38 ++ .../SierraXMLCompletionProvider.java | 302 ++++++++++ .../previewer/engine/RenderingEngine.java | 69 +++ .../sierra/previewer/model/RenderError.java | 29 + .../sierra/previewer/model/RenderResult.java | 36 ++ .../httprpc/sierra/previewer/MainFrame.xml | 26 +- .../src/main/resources/sierra.dtd | 107 ++++ .../src/main/resources/sierra.png | Bin 0 -> 711 bytes .../SierraXMLCompletionProviderTest.java | 167 ++++++ .../src/test/resources/sierra.dtd | 107 ++++ 14 files changed, 1520 insertions(+), 7 deletions(-) create mode 100644 sierra-previewer/gradle.properties create mode 100644 sierra-previewer/src/main/java/org/httprpc/sierra/previewer/RecentFilesManager.java create mode 100644 sierra-previewer/src/main/java/org/httprpc/sierra/previewer/SierraPreviewerApp.java create mode 100644 sierra-previewer/src/main/java/org/httprpc/sierra/previewer/SierraXMLCompletionProvider.java create mode 100644 sierra-previewer/src/main/java/org/httprpc/sierra/previewer/engine/RenderingEngine.java create mode 100644 sierra-previewer/src/main/java/org/httprpc/sierra/previewer/model/RenderError.java create mode 100644 sierra-previewer/src/main/java/org/httprpc/sierra/previewer/model/RenderResult.java create mode 100644 sierra-previewer/src/main/resources/sierra.dtd create mode 100644 sierra-previewer/src/main/resources/sierra.png create mode 100644 sierra-previewer/src/test/java/org/httprpc/sierra/previewer/SierraXMLCompletionProviderTest.java create mode 100644 sierra-previewer/src/test/resources/sierra.dtd diff --git a/sierra-previewer/build.gradle b/sierra-previewer/build.gradle index 66b3321c..3be65672 100644 --- a/sierra-previewer/build.gradle +++ b/sierra-previewer/build.gradle @@ -24,6 +24,16 @@ dependencies { implementation 'com.fifesoft:rsyntaxtextarea:3.6.0' implementation 'com.fifesoft:autocomplete:3.3.2' + + // Test dependencies based on your pom.xml + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.1' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.1' + testImplementation 'org.mockito:mockito-core:5.9.0' + testImplementation 'org.mockito:mockito-junit-jupiter:5.9.0' + + // This allows the JUnit Platform to discover and execute the Jupiter tests (@Test, etc.) + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.1' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.withType(JavaCompile) { @@ -31,3 +41,8 @@ tasks.withType(JavaCompile) { '-parameters' ] } + +tasks.named('test', Test) { + // This tells Gradle to use the JUnit Platform (needed for modern JUnit 5 tests) + useJUnitPlatform() +} diff --git a/sierra-previewer/gradle.properties b/sierra-previewer/gradle.properties new file mode 100644 index 00000000..e69de29b diff --git a/sierra-previewer/src/main/java/org/httprpc/sierra/previewer/MainFrame.java b/sierra-previewer/src/main/java/org/httprpc/sierra/previewer/MainFrame.java index bc4ca317..14187e8a 100644 --- a/sierra-previewer/src/main/java/org/httprpc/sierra/previewer/MainFrame.java +++ b/sierra-previewer/src/main/java/org/httprpc/sierra/previewer/MainFrame.java @@ -11,9 +11,526 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.httprpc.sierra.previewer; -public class MainFrame { - // TODO +import org.httprpc.sierra.previewer.engine.RenderingEngine; +import org.httprpc.sierra.previewer.model.RenderError; +import org.httprpc.sierra.previewer.model.RenderResult; +import java.awt.*; +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.function.Consumer; +import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.event.DocumentListener; +import javax.swing.filechooser.FileNameExtensionFilter; + +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; + +import org.fife.ui.autocomplete.AutoCompletion; +import org.fife.ui.autocomplete.CompletionProvider; + +import org.httprpc.sierra.UILoader; +import org.httprpc.sierra.Outlet; + +/** + * The main application window for the Sierra UI Previewer. UI is defined in + * MainFrame.xml and loaded by UILoader. This class contains the wiring and + * business logic. + */ +public class MainFrame extends JFrame { + + // --- Subsystems --- + private final RenderingEngine renderingEngine; + private final Timer debounceTimer; + private final RecentFilesManager recentFilesManager; // NEW: Manager instance + + // --- File Handling State --- + private final JFileChooser fileChooser; + private Path currentFilePath = null; // Stores the path of the currently loaded file + + // --- UI Components (Injected by Sierra) --- + @Outlet + private JScrollPane editorScrollPane; // The placeholder + + @Outlet + private JPanel previewPanel; // The + + @Outlet + private JLabel statusBar; + + @Outlet + private JLabel filePathLabel; // The \ No newline at end of file diff --git a/sierra-previewer/src/main/resources/sierra.dtd b/sierra-previewer/src/main/resources/sierra.dtd new file mode 100644 index 00000000..a3f336b7 --- /dev/null +++ b/sierra-previewer/src/main/resources/sierra.dtd @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sierra-previewer/src/main/resources/sierra.png b/sierra-previewer/src/main/resources/sierra.png new file mode 100644 index 0000000000000000000000000000000000000000..c595fc0b39be012f429df33009c63d287dd20d1f GIT binary patch literal 711 zcmeAS@N?(olHy`uVBq!ia0vp^TR@nD4M^IaWitX&Y)RhkE)4%caKYZ?lNlJ8YCK&W zLn`LHy<_MVlPJ-4G5^q-15qkwlcwBsJ>hrcE6empMwi$eCDNFa^!;{yIT*jL(k7iz zKmOx~;?>s7KoghwuJ8f*VoU)oImq7+bxWx*4+5M_?rWF&-|%4 zdtf=Mdrjm9Mq}gnct*VOl9 zFTZ>iNO9^@!CVTRMW*&sb+4K4oqAca`73A60d8uA5sG6@U9$fn-+$cF+B(|O^UmeV zmoM#I>bQT;o->ahKR)I8LtWd>vQGa-!%SA)w_-AdrpDWiKUW?UlfRyrwl4iy-D7K5 ddI8dAAK71Q)?i30S?miE^>p=fS?83{1OVxN6vY4l literal 0 HcmV?d00001 diff --git a/sierra-previewer/src/test/java/org/httprpc/sierra/previewer/SierraXMLCompletionProviderTest.java b/sierra-previewer/src/test/java/org/httprpc/sierra/previewer/SierraXMLCompletionProviderTest.java new file mode 100644 index 00000000..ce63b2a9 --- /dev/null +++ b/sierra-previewer/src/test/java/org/httprpc/sierra/previewer/SierraXMLCompletionProviderTest.java @@ -0,0 +1,167 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.httprpc.sierra.previewer; + +import org.fife.ui.autocomplete.Completion; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import javax.swing.text.BadLocationException; +import javax.swing.text.JTextComponent; +import javax.swing.text.PlainDocument; +import javax.swing.text.Document; + +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * Unit test for SierraXMLCompletionProvider focusing only on core element and attribute completion logic. + * This test ensures that the provider correctly reads the 'sierra.dtd' and suggests: + * 1. All UI element tags when starting a tag. + * 2. Relevant attributes when inside a known tag. + */ +public class SierraXMLCompletionProviderTest { + + private SierraXMLCompletionProvider provider; + private JTextComponent mockComponent; + + @BeforeEach + void setUp() { + // Initializes the provider, which attempts to load and parse the DTD from the classpath. + provider = new SierraXMLCompletionProvider(); + mockComponent = mock(JTextComponent.class); + + // Use a simple PlainDocument for getText() calls to work cleanly + Document doc = new PlainDocument(); + when(mockComponent.getDocument()).thenReturn(doc); + } + + /** + * Helper to simulate text insertion into the component and set the caret position. + * It also mocks the getText(int, int) call to read from the internal document. + */ + private void setComponentText(String text, int caretOffset) throws BadLocationException { + Document doc = mockComponent.getDocument(); + doc.remove(0, doc.getLength()); + doc.insertString(0, text, null); + + when(mockComponent.getText(anyInt(), anyInt())).thenAnswer(invocation -> { + int start = invocation.getArgument(0); + int len = invocation.getArgument(1); + return doc.getText(start, len); + }); + when(mockComponent.getCaretPosition()).thenReturn(caretOffset); + } + + // --- Core Test Case: 1. Tag Completion --- + + @Test + void testCompletion_StartTag_SuggestsAllUIElements() throws BadLocationException { + // Simulate typing '<' to trigger tag completion (caret at offset 1) + setComponentText("<", 1); + + List suggestions = provider.getCompletions(mockComponent); + assertFalse(suggestions.isEmpty(), "The provider should suggest elements after typing '<'."); + + // Collect the suggested tag names + Set tagNames = suggestions.stream() + .map(Completion::getInputText) + .collect(Collectors.toSet()); + + // Verify the total count of elements parsed from the DTD + // This count (32) must match the total number of tags in sierra.dtd + final int EXPECTED_ELEMENT_COUNT = 32; + assertEquals(EXPECTED_ELEMENT_COUNT, suggestions.size(), + "Should have parsed exactly " + EXPECTED_ELEMENT_COUNT + " elements based on the DTD content."); + + // Verify a selection of known tags from the DTD are present + assertTrue(tagNames.contains("button"), "Should contain 'button' tag."); + assertTrue(tagNames.contains("label"), "Should contain 'label' tag."); + assertTrue(tagNames.contains("activity-indicator"), "Should contain 'activity-indicator' tag."); + + // Ensure suggestions are alphabetically sorted + for (int i = 0; i < suggestions.size() - 1; i++) { + String current = suggestions.get(i).getInputText(); + String next = suggestions.get(i + 1).getInputText(); + assertTrue(current.compareTo(next) <= 0, "Suggestions should be sorted alphabetically."); + } + } + + // --- Core Test Case: 2. Attribute Completion for