├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── LICENSE
├── README.md
├── diagrams
├── UseCase.puml
└── UseCase_dark.puml
├── pom.xml
├── resources
├── MainFrame.png
└── SplashScreen.png
└── src
├── main
├── java
│ └── org
│ │ └── example
│ │ ├── App.java
│ │ ├── AppImpl.java
│ │ ├── AppSplashScreen.java
│ │ ├── AppSplashScreenImpl.java
│ │ ├── MainFrame.java
│ │ ├── MainFrameImpl.java
│ │ ├── PasswordGenerator.java
│ │ ├── PasswordGeneratorImpl.java
│ │ ├── SpringMainConfig.java
│ │ ├── TaskLoadApplication.java
│ │ └── TaskLoadApplicationImpl.java
└── resources
│ ├── copy-icon.png
│ ├── dice-icon.png
│ └── splash_animation.gif
└── test
└── java
└── org
└── example
└── AppImplTest.java
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | # Sequence of patterns matched against refs/tags
4 | tags:
5 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
6 |
7 | name: Create Release
8 |
9 | jobs:
10 | build:
11 | name: Create Release
12 | runs-on: ubuntu-latest
13 | steps:
14 | - name: Checkout code
15 | uses: actions/checkout@master
16 | - name: Create Release
17 | id: create_release
18 | uses: actions/create-release@latest
19 | env:
20 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21 | with:
22 | tag_name: ${{ github.ref }}
23 | release_name: Release ${{ github.ref }}
24 | body: |
25 | **Release Notes:**
26 | - Added the Maven Dependency Plugin to automatically create a target/lib folder containing all project dependencies. This enhancement streamlines the packaging process, making it easier to manage and include external libraries required for project execution.
27 | draft: false
28 | prerelease: false
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ##############################
2 | ## Java
3 | ##############################
4 | .mtj.tmp/
5 | *.class
6 | *.jar
7 | *.war
8 | *.ear
9 | *.nar
10 | hs_err_pid*
11 |
12 | ##############################
13 | ## Maven
14 | ##############################
15 | target/
16 | pom.xml.tag
17 | pom.xml.releaseBackup
18 | pom.xml.versionsBackup
19 | pom.xml.next
20 | pom.xml.bak
21 | release.properties
22 | dependency-reduced-pom.xml
23 | buildNumber.properties
24 | .mvn/timing.properties
25 | .mvn/wrapper/maven-wrapper.jar
26 |
27 | ##############################
28 | ## Gradle
29 | ##############################
30 | bin/
31 | build/
32 | .gradle
33 | .gradletasknamecache
34 | gradle-app.setting
35 | !gradle-wrapper.jar
36 |
37 | ##############################
38 | ## IntelliJ
39 | ##############################
40 | out/
41 | .idea/
42 | .idea_modules/
43 | *.iml
44 | *.ipr
45 | *.iws
46 |
47 | ##############################
48 | ## Eclipse
49 | ##############################
50 | .settings/
51 | bin/
52 | tmp/
53 | .metadata
54 | .classpath
55 | .project
56 | *.tmp
57 | *.bak
58 | *.swp
59 | *~.nib
60 | local.properties
61 | .loadpath
62 | .factorypath
63 |
64 | ##############################
65 | ## NetBeans
66 | ##############################
67 | nbproject/private/
68 | build/
69 | nbbuild/
70 | dist/
71 | nbdist/
72 | nbactions.xml
73 | nb-configuration.xml
74 |
75 | ##############################
76 | ## Visual Studio Code
77 | ##############################
78 | .vscode/
79 | .code-workspace
80 |
81 | ##############################
82 | ## OS X
83 | ##############################
84 | .DS_Store
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Velimir Đurković
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # demo-java-swing
2 |
3 | ## Password Generator Application
4 |
5 | Welcome to the Password Generator Application! This tool is designed to help users effortlessly create secure passwords
6 | that are 16 characters long. It will create a unique combination of uppercase letters, lowercase letters, numbers, and
7 | special symbols to ensure strong security, making it suitable for protecting sensitive accounts and personal
8 | information. The generated password will comply with best practices for complexity and randomness, eliminating the need
9 | for users to create their own passwords while enhancing their online safety. Whether you're setting up a new account,
10 | enhancing your cybersecurity, or simply in need of a reliable password, this solution has got you covered. No additional
11 | options or complex settings are necessary; just generate and use your password with confidence! The code is open-source,
12 | inviting contributions and modifications from the community to enhance functionality while keeping safety at the
13 | forefront. Start protecting your digital life today with our Password Generator Application!
14 |
15 | ## Use Case Diagram
16 |
17 | A use case diagram for a password generator application illustrates the interactions between users and the system. In
18 | this diagram, two primary use cases are highlighted: "Generate Password" and "Copy Password." The "Generate Password"
19 | use case allows users to create secure, random passwords. Meanwhile, the "Copy Password" use case enables users to
20 | easily transfer generated passwords to their clipboard for seamless pasting into login fields. Together, these use cases
21 | enhance user experience by providing straightforward tools for password management and security.
22 |
23 |
24 |
25 |
26 |
27 |
28 | ## Splash Screen
29 |
30 | 
31 |
32 | ## Main Frame
33 |
34 | 
35 |
--------------------------------------------------------------------------------
/diagrams/UseCase.puml:
--------------------------------------------------------------------------------
1 | @startuml
2 | left to right direction
3 |
4 | actor "User" as user
5 |
6 | rectangle demo-java-swing {
7 | usecase "Copy Password" as copyPassword
8 | usecase "Generate Password" as generatePassword
9 | }
10 |
11 | user --> generatePassword
12 | user --> copyPassword
13 | @enduml
--------------------------------------------------------------------------------
/diagrams/UseCase_dark.puml:
--------------------------------------------------------------------------------
1 | @startuml UseCase
2 | !theme crt-green
3 | !include https://raw.githubusercontent.com/djvelimir/demo-java-swing/main/diagrams/UseCase.puml
4 | @enduml
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 | 4.0.0
6 |
7 | org.example
8 | demo-java-swing
9 | 1.0.1
10 |
11 | demo-java-swing
12 | https://djvelimir.github.io
13 |
14 |
15 | UTF-8
16 | 21
17 | 21
18 |
19 |
20 |
21 |
22 | org.junit.jupiter
23 | junit-jupiter-api
24 | 5.11.4
25 | test
26 |
27 |
28 | org.junit.jupiter
29 | junit-jupiter-engine
30 | 5.11.4
31 | test
32 |
33 |
34 | org.mockito
35 | mockito-junit-jupiter
36 | 5.14.2
37 | test
38 |
39 |
40 | org.mockito
41 | mockito-core
42 | 5.14.2
43 | test
44 |
45 |
46 | net.bytebuddy
47 | byte-buddy-agent
48 | 1.15.4
49 | test
50 |
51 |
52 | org.springframework
53 | spring-context
54 | 6.2.1
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 | maven-clean-plugin
64 | 3.4.0
65 |
66 |
67 |
68 | maven-resources-plugin
69 | 3.3.1
70 |
71 |
72 | maven-compiler-plugin
73 | 3.13.0
74 |
75 |
76 | maven-surefire-plugin
77 | 3.5.1
78 |
79 |
80 | maven-jar-plugin
81 | 3.4.2
82 |
83 |
84 | maven-dependency-plugin
85 | 3.7.0
86 |
87 |
88 | maven-install-plugin
89 | 3.1.2
90 |
91 |
92 | maven-deploy-plugin
93 | 3.1.2
94 |
95 |
96 |
97 | maven-site-plugin
98 | 3.20.0
99 |
100 |
101 | maven-project-info-reports-plugin
102 | 3.6.2
103 |
104 |
105 |
106 |
107 |
108 | org.apache.maven.plugins
109 | maven-surefire-plugin
110 |
111 | -javaagent:${settings.localRepository}/net/bytebuddy/byte-buddy-agent/1.15.4/byte-buddy-agent-1.15.4.jar
112 |
113 |
114 |
115 | org.apache.maven.plugins
116 | maven-jar-plugin
117 |
118 |
119 |
120 | true
121 | lib/
122 | org.example.AppImpl
123 |
124 |
125 |
126 |
127 |
128 | org.apache.maven.plugins
129 | maven-dependency-plugin
130 |
131 |
132 | copy-libs
133 | package
134 |
135 | copy-dependencies
136 |
137 |
138 | runtime
139 | false
140 | true
141 | ${project.build.directory}/lib
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
--------------------------------------------------------------------------------
/resources/MainFrame.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djvelimir/demo-java-swing/3cb780365ceb9b2a230662b4be3f3a3de478d069/resources/MainFrame.png
--------------------------------------------------------------------------------
/resources/SplashScreen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djvelimir/demo-java-swing/3cb780365ceb9b2a230662b4be3f3a3de478d069/resources/SplashScreen.png
--------------------------------------------------------------------------------
/src/main/java/org/example/App.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | public interface App {
4 | void start();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/example/AppImpl.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.context.ApplicationContext;
5 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
6 | import org.springframework.stereotype.Component;
7 |
8 | import javax.swing.*;
9 |
10 | /**
11 | * Swing application
12 | */
13 | @Component
14 | public class AppImpl implements App {
15 |
16 | private final TaskLoadApplication taskLoadApplication;
17 |
18 | @Autowired
19 | public AppImpl(TaskLoadApplication taskLoadApplication) {
20 | this.taskLoadApplication = taskLoadApplication;
21 | }
22 |
23 | public static void main(String[] args) {
24 | ApplicationContext context = new AnnotationConfigApplicationContext(SpringMainConfig.class);
25 | App app = context.getBean(App.class);
26 | app.start();
27 | }
28 |
29 | @Override
30 | public void start() {
31 | SwingUtilities.invokeLater(taskLoadApplication::execute);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/org/example/AppSplashScreen.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | public interface AppSplashScreen {
4 | void show();
5 |
6 | void hide();
7 |
8 | void dispose();
9 |
10 | void updateProgress(String progressString, int progressValue);
11 | }
12 |
--------------------------------------------------------------------------------
/src/main/java/org/example/AppSplashScreenImpl.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Component;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 | import java.util.Objects;
9 |
10 | @Component
11 | public class AppSplashScreenImpl implements AppSplashScreen {
12 |
13 | private final JDialog dialog = new JDialog();
14 | private final ImageIcon imageIcon = new ImageIcon(Objects.requireNonNull(this.getClass().getResource("/splash_animation.gif")));
15 | private final JLabel label = new JLabel(imageIcon);
16 | private final JProgressBar progressBar = new JProgressBar();
17 |
18 | @Autowired
19 | public AppSplashScreenImpl() {
20 | dialog.setUndecorated(true);
21 | dialog.getContentPane().add(label, BorderLayout.CENTER);
22 | dialog.getContentPane().add(progressBar, BorderLayout.PAGE_END);
23 | dialog.pack();
24 | dialog.setLocationRelativeTo(null);
25 | }
26 |
27 | @Override
28 | public void show() {
29 | dialog.setVisible(true);
30 | }
31 |
32 | @Override
33 | public void hide() {
34 | dialog.setVisible(false);
35 | }
36 |
37 | @Override
38 | public void dispose() {
39 | dialog.dispose();
40 | }
41 |
42 | @Override
43 | public void updateProgress(String progressString, int progressValue) {
44 | progressBar.setValue(progressValue);
45 | progressBar.setStringPainted(true);
46 | progressBar.setString(progressString);
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/org/example/MainFrame.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | public interface MainFrame {
4 | void show();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/example/MainFrameImpl.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Component;
5 |
6 | import javax.swing.*;
7 | import java.awt.*;
8 | import java.util.Objects;
9 |
10 | @Component
11 | public class MainFrameImpl implements MainFrame {
12 |
13 | private final PasswordGenerator passwordGenerator;
14 | private final JFrame frame = new JFrame();
15 | private final Icon iconCopy = new ImageIcon(Objects.requireNonNull(this.getClass().getResource("/copy-icon.png")));
16 | private final Icon iconDice = new ImageIcon(Objects.requireNonNull(this.getClass().getResource("/dice-icon.png")));
17 | private final JPasswordField txtGeneratedPassword = new JPasswordField();
18 | private final JButton btnGeneratePassword = new JButton(iconDice);
19 | private final JButton btnCopyPassword = new JButton(iconCopy);
20 |
21 | @Autowired
22 | public MainFrameImpl(PasswordGenerator passwordGenerator) {
23 | this.passwordGenerator = passwordGenerator;
24 |
25 | frame.setTitle("demo-java-swing");
26 | frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
27 |
28 | btnGeneratePassword.setToolTipText("Generate Password");
29 | btnCopyPassword.setToolTipText("Copy Password");
30 |
31 | JToolBar toolBar = new JToolBar();
32 | toolBar.setFloatable(false);
33 | toolBar.add(btnGeneratePassword);
34 | toolBar.add(btnCopyPassword);
35 |
36 | JPanel panel = new JPanel(new BorderLayout());
37 | panel.add(toolBar, BorderLayout.EAST);
38 | panel.add(txtGeneratedPassword, BorderLayout.CENTER);
39 |
40 | frame.getContentPane().add(panel, BorderLayout.CENTER);
41 |
42 | txtGeneratedPassword.setPreferredSize(new Dimension(350, 24));
43 | frame.pack();
44 | frame.setLocationRelativeTo(null);
45 |
46 | btnCopyPassword.addActionListener(e -> {
47 | txtGeneratedPassword.putClientProperty("JPasswordField.cutCopyAllowed", true);
48 | txtGeneratedPassword.selectAll();
49 | txtGeneratedPassword.copy();
50 | });
51 |
52 | btnGeneratePassword.addActionListener(e -> {
53 | String generatedPassword = this.passwordGenerator.generate();
54 | txtGeneratedPassword.setText(generatedPassword);
55 | });
56 | }
57 |
58 | @Override
59 | public void show() {
60 | frame.setVisible(true);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/org/example/PasswordGenerator.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | public interface PasswordGenerator {
4 | String generate();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/example/PasswordGeneratorImpl.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.springframework.stereotype.Component;
4 |
5 | import java.util.Arrays;
6 | import java.util.Collections;
7 | import java.util.List;
8 | import java.util.Random;
9 |
10 | @Component
11 | public class PasswordGeneratorImpl implements PasswordGenerator {
12 | private static final int PASSWORD_LENGTH = 16;
13 | private static final String UPPERCASE_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
14 | private static final String LOWERCASE_CHARACTERS = "abcdefghijklmnopqrstuvwxyz";
15 | private static final String DIGIT_CHARACTERS = "0123456789";
16 | private static final String SPECIAL_CHARACTERS = "~`!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?";
17 | private static final String UNION_OF_ALLOWED_CHARACTERS = UPPERCASE_CHARACTERS
18 | .concat(LOWERCASE_CHARACTERS)
19 | .concat(DIGIT_CHARACTERS)
20 | .concat(SPECIAL_CHARACTERS);
21 | private static final Random RANDOM_OBJECT = new Random();
22 |
23 | /**
24 | * Generate random password
25 | * Generated password length is 16
26 | * Generated password contains at least one uppercase character
27 | * Generated password contains at least one lowercase character
28 | * Generated password contains at least one digit character
29 | * Generated password contains at least one special character
30 | *
31 | * @return generated password
32 | */
33 | @Override
34 | public String generate() {
35 | var stringBuilder = new StringBuilder();
36 |
37 | // generate at least one uppercase character
38 | stringBuilder.append(generateRandomCharacter(UPPERCASE_CHARACTERS));
39 |
40 | // generate at least one lowercase character
41 | stringBuilder.append(generateRandomCharacter(LOWERCASE_CHARACTERS));
42 |
43 | // generate at least one digit character
44 | stringBuilder.append(generateRandomCharacter(DIGIT_CHARACTERS));
45 |
46 | // generate at least one special character
47 | stringBuilder.append(generateRandomCharacter(SPECIAL_CHARACTERS));
48 |
49 | for (int i = 4; i < PASSWORD_LENGTH; i++) {
50 | // generate random character from union of allowed characters
51 | stringBuilder.append(generateRandomCharacter(UNION_OF_ALLOWED_CHARACTERS));
52 | }
53 |
54 | // shuffle generated characters
55 | List ch = Arrays.asList(stringBuilder.toString().split(""));
56 | Collections.shuffle(ch);
57 |
58 | // return generated password
59 | return String.join("", ch);
60 | }
61 |
62 | private char generateRandomCharacter(String characters) {
63 | return characters.charAt(RANDOM_OBJECT.nextInt(characters.length()));
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/src/main/java/org/example/SpringMainConfig.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.springframework.context.annotation.ComponentScan;
4 | import org.springframework.context.annotation.Configuration;
5 |
6 | @Configuration
7 | @ComponentScan("org.example")
8 | public class SpringMainConfig {
9 | }
10 |
--------------------------------------------------------------------------------
/src/main/java/org/example/TaskLoadApplication.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | public interface TaskLoadApplication {
4 | void execute();
5 | }
6 |
--------------------------------------------------------------------------------
/src/main/java/org/example/TaskLoadApplicationImpl.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Component;
5 |
6 | import javax.swing.*;
7 | import java.util.List;
8 | import java.util.concurrent.ExecutionException;
9 | import java.util.logging.Logger;
10 |
11 | @Component
12 | public class TaskLoadApplicationImpl extends SwingWorker implements TaskLoadApplication {
13 |
14 | private static final int NUMBER_OF_STEPS = 30;
15 | private final Logger logger = Logger.getLogger(this.getClass().getName());
16 | private final AppSplashScreen splashScreen;
17 | private final MainFrame mainFrame;
18 |
19 | @Autowired
20 | public TaskLoadApplicationImpl(AppSplashScreen splashScreen, MainFrame mainFrame) {
21 | this.splashScreen = splashScreen;
22 | this.mainFrame = mainFrame;
23 | }
24 |
25 | @Override
26 | protected void process(List chunks) {
27 | int currentStep = chunks.getLast();
28 |
29 | if (currentStep == 1) {
30 | splashScreen.show();
31 | }
32 |
33 | splashScreen.updateProgress((int) (((double) currentStep / NUMBER_OF_STEPS) * 100) + "%", currentStep * 100 / NUMBER_OF_STEPS);
34 | }
35 |
36 | @Override
37 | protected Void doInBackground() throws Exception {
38 | for (int currentStep = 1; currentStep <= NUMBER_OF_STEPS; currentStep++) {
39 | publish(currentStep);
40 |
41 | // Illustrating long-running code.
42 | Thread.sleep(100);
43 | }
44 |
45 | return null;
46 | }
47 |
48 | @Override
49 | protected void done() {
50 | try {
51 | get();
52 | splashScreen.hide();
53 | splashScreen.dispose();
54 | mainFrame.show();
55 | } catch (InterruptedException e) {
56 | logger.severe(e.toString());
57 | Thread.currentThread().interrupt();
58 | } catch (ExecutionException e) {
59 | logger.severe(e.toString());
60 | System.exit(0);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/resources/copy-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djvelimir/demo-java-swing/3cb780365ceb9b2a230662b4be3f3a3de478d069/src/main/resources/copy-icon.png
--------------------------------------------------------------------------------
/src/main/resources/dice-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djvelimir/demo-java-swing/3cb780365ceb9b2a230662b4be3f3a3de478d069/src/main/resources/dice-icon.png
--------------------------------------------------------------------------------
/src/main/resources/splash_animation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/djvelimir/demo-java-swing/3cb780365ceb9b2a230662b4be3f3a3de478d069/src/main/resources/splash_animation.gif
--------------------------------------------------------------------------------
/src/test/java/org/example/AppImplTest.java:
--------------------------------------------------------------------------------
1 | package org.example;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.junit.jupiter.api.extension.ExtendWith;
5 | import org.mockito.junit.jupiter.MockitoExtension;
6 |
7 | import static org.junit.jupiter.api.Assertions.assertTrue;
8 |
9 | /**
10 | * Unit test for simple App.
11 | */
12 | @ExtendWith(MockitoExtension.class)
13 | class AppImplTest {
14 | /**
15 | * Rigorous Test :-)
16 | */
17 | @Test
18 | void shouldAnswerWithTrue() {
19 | assertTrue(true);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------