assertj / assertj-swing

Fluent assertions for Swing apps
Other
108 stars 52 forks source link

Unable to find component using matcher | Fail on Ubuntu #254

Open Remeic opened 4 years ago

Remeic commented 4 years ago

Hi, i have to test my java swing ui with assertj swing, on my mac i have no error but on latest and previous ubuntu version, i have this issue Unable to find component using matcher (the stacktrace is at the end of this post)

Running on Java 8 or 11 same issue, assertj swing version 3.17.0 I have to set timeout before testing ui?

Here a snippet code of my tests

        @Before
    public void onSetUp() {
        MockitoAnnotations.initMocks(this);
        GuiActionRunner.execute(() -> {
            accountSwingView = new AccountSwingView();
            accountSwingView.setAccountController(accountController);
            return accountSwingView;
        });

        window = new FrameFixture(robot(), accountSwingView);
        window.show(); // shows the frame to test

    }

    @Test
    @GUITest
    public void testModifyPasswordButtonDelegateToController() {
        final String UPDATED_PASSWORD = "newPassword";
        List<Account> accounts = Arrays.asList(new Account("github.com", new Credential("giulio", "passgiulio")));
        accountSwingView.setListAccountTableData(accounts);

        // Verify modifyUsername called when action performed on Modify Password Button
        window.tabbedPane("tabbedPanel").selectTab(1);
        window.panel("panelDisplayedAccounts").focus();
        window.scrollPane("scrollPaneAccounts").focus();
        window.table("tableDisplayedAccounts").focus();
        window.table("tableDisplayedAccounts").selectRows(0);
        window.textBox("textFieldUpdateCell").enterText(UPDATED_PASSWORD);
        window.button("buttonModifyPassword").click();
        verify(accountController).modifyPassword(new Account("github.com", new Credential("giulio", "passgiulio")),
                UPDATED_PASSWORD);
    }

    @Test
    @GUITest
    public void testShowAccountsDisplayCorrectAccountsIntoTable() {
        Account firstAccount = new Account("github.com", new Credential("giulio", "passgiulio"));
        Account secondAccount = new Account("github.com", new Credential("remeic", "remegiulio"));
        List<Account> accountDisplayed = Arrays.asList(firstAccount, secondAccount);
        accountSwingView.showAccounts(accountDisplayed);
        window.tabbedPane("tabbedPanel").selectTab(1);
        window.panel("panelDisplayedAccounts").focus();
        List<Account> accountList = getAccountsList(window.table("tableDisplayedAccounts").contents());
        assertThat(accountList).containsAll(accountDisplayed);
    }

    @Test
    @GUITest
    public void testAccountIsModifiedShowLabelWithSuccessInfo() {
        window.tabbedPane("tabbedPanel").selectTab(1);
        window.panel("panelDisplayedAccounts").focus();
        window.label("labelOperationResult").requireDisabled();
        window.label("labelOperationResult").requireText("");
        accountSwingView.accountIsModified();
        window.label("labelOperationResult").requireEnabled();
        window.label("labelOperationResult").requireText("Account Modified!");

    }
Unable to find component using matcher org.assertj.swing.core.NameMatcher[name='panelDisplayedAccounts', type=javax.swing.JPanel, requireShowing=true].

Component hierarchy:
dev.justgiulio.passwordmanager.view.swing.AccountSwingView[name='frame12', title='Password Manager', enabled=true, visible=true, showing=true]
  javax.swing.JRootPane[]
    javax.swing.JPanel[name='null.glassPane']
    javax.swing.JLayeredPane[]
      javax.swing.JPanel[name='null.contentPane']
        javax.swing.JTabbedPane[name='tabbedPanel', selectedTabIndex=0, selectedTabTitle='Add | Generate Password', tabCount=2, tabTitles=["Add | Generate Password", "Saved Password"], enabled=true, visible=true, showing=true
          javax.swing.JPanel[name='panelGeneratePassword']
            javax.swing.JPanel[name=null]
              javax.swing.JButton[name='buttonSaveAccount', text='Save', enabled=false, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Site', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='New Account', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldSiteName', text='', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldUsername', text='', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldPassword', text='', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Username', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Password', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name='labelErrorMessage', text='', enabled=false, visible=true, showing=true]
              javax.swing.JLabel[name='labelAccountAdded', text='', enabled=false, visible=true, showing=true]
              javax.swing.JSeparator[,321,11,2x326,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,orientation=VERTICAL]
            javax.swing.JPanel[name=null]
              javax.swing.JLabel[name=null, text='Strength', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Passowrd Generator', enabled=true, visible=true, showing=true]
              javax.swing.JRadioButton[name='radioButtonLowStrength', text='Low', selected=false, enabled=true, visible=true, showing=true]
              javax.swing.JRadioButton[name='radioButtonMediumStrength', text='Medium', selected=false, enabled=true, visible=true, showing=true]
              javax.swing.JRadioButton[name='radioButtonHighStrength', text='High', selected=true, enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Length', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldGeneratedPassword', text='', enabled=true, visible=true, showing=true]
              javax.swing.JButton[name='buttonGeneratePassword', text='Generate', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Generated Password', enabled=true, visible=true, showing=true]
              javax.swing.JSlider[name='sliderPasswordLength', value=8, minimum=8, maximum=32, enabled=true, visible=true, showing=true]
          javax.swing.JPanel[name='panelDisplayedAccounts']
            javax.swing.JLabel[name=null, text='Accounts', enabled=true, visible=true, showing=false]
            javax.swing.JButton[name='buttonFindAllAccounts', text='Find All', enabled=true, visible=true, showing=false]
            javax.swing.JSeparator[,115,46,21x27,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,orientation=VERTICAL]
            javax.swing.JLabel[name=null, text='Text to FInd', enabled=true, visible=true, showing=false]
            javax.swing.JTextField[name='textFieldSearchText', text='', enabled=true, visible=true, showing=false]

javax.swing.JButton[name='buttonFindBySiteAccounts', text='Find by Site', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonFindByUsernameAccounts', text='Find By Username', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonFindByPasswordAccounts', text='Find By Password', enabled=false, visible=true, showing=false]
            javax.swing.JScrollPane[name='scrollPaneAccounts', enabled=true, visible=true, showing=false]
              javax.swing.JViewport[,1,20,928x192,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=,scrollUnderway=false]
                javax.swing.JTable[name='tableDisplayedAccounts', rowCount=0, columnCount=3, enabled=true, visible=true, showing=false]
                  javax.swing.CellRendererPane[,0,0,0x0,hidden]
              javax.swing.JScrollPane$ScrollBar[name=null, value=0, blockIncrement=10, minimum=0, maximum=0, enabled=true, visible=false, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
              javax.swing.JScrollPane$ScrollBar[name=null, value=0, blockIncrement=10, minimum=0, maximum=928, enabled=true, visible=false, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
              javax.swing.JViewport[,1,1,928x19,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=,scrollUnderway=false]
                javax.swing.table.JTableHeader[,0,0,928x19,alignmentX=0.0,alignmentY=0.0,border=,flags=16777544,maximumSize=,minimumSize=,preferredSize=,draggedDistance=0,reorderingAllowed=true,resizingAllowed=true,updateTableInRealTime=true]
                  javax.swing.CellRendererPane[,0,0,0x0,hidden]
            javax.swing.JButton[name='buttonDeleteAccount', text='Delete', enabled=false, visible=true, showing=false]
            javax.swing.JSeparator[,99,311,2x41,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,orientation=VERTICAL]
            javax.swing.JTextField[name='textFieldUpdateCell', text='', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonModifyUsername', text='Modify Username', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonModifyPassword', text='Modify Password', enabled=false, visible=true, showing=false]
            javax.swing.JLabel[name='labelOperationResult', text='', enabled=false, visible=true, showing=false]
        javax.swing.JLabel[name=null, text='Password Manager | Giulio Fagioli 6006222', enabled=true, visible=true, showing=true]

org.assertj.swing.exception.ComponentLookupException
Unable to find component using matcher org.assertj.swing.core.NameMatcher[name='panelDisplayedAccounts', type=javax.swing.JPanel, requireShowing=true].
Component hierarchy:
dev.justgiulio.passwordmanager.view.swing.AccountSwingView[name='frame12', title='Password Manager', enabled=true, visible=true, showing=true]
  javax.swing.JRootPane[]
    javax.swing.JPanel[name='null.glassPane']
    javax.swing.JLayeredPane[]
      javax.swing.JPanel[name='null.contentPane']
        javax.swing.JTabbedPane[name='tabbedPanel', selectedTabIndex=0, selectedTabTitle='Add | Generate Password', tabCount=2, tabTitles=["Add | Generate Password", "Saved Password"], enabled=true, visible=true, showing=true
          javax.swing.JPanel[name='panelGeneratePassword']
            javax.swing.JPanel[name=null]
              javax.swing.JButton[name='buttonSaveAccount', text='Save', enabled=false, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Site', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='New Account', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldSiteName', text='', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldUsername', text='', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldPassword', text='', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Username', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Password', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name='labelErrorMessage', text='', enabled=false, visible=true, showing=true]
              javax.swing.JLabel[name='labelAccountAdded', text='', enabled=false, visible=true, showing=true]
              javax.swing.JSeparator[,321,11,2x326,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,orientation=VERTICAL]
            javax.swing.JPanel[name=null]
              javax.swing.JLabel[name=null, text='Strength', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Passowrd Generator', enabled=true, visible=true, showing=true]
              javax.swing.JRadioButton[name='radioButtonLowStrength', text='Low', selected=false, enabled=true, visible=true, showing=true]
              javax.swing.JRadioButton[name='radioButtonMediumStrength', text='Medium', selected=false, enabled=true, visible=true, showing=true]
              javax.swing.JRadioButton[name='radioButtonHighStrength', text='High', selected=true, enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Length', enabled=true, visible=true, showing=true]
              javax.swing.JTextField[name='textFieldGeneratedPassword', text='', enabled=true, visible=true, showing=true]
              javax.swing.JButton[name='buttonGeneratePassword', text='Generate', enabled=true, visible=true, showing=true]
              javax.swing.JLabel[name=null, text='Generated Password', enabled=true, visible=true, showing=true]
              javax.swing.JSlider[name='sliderPasswordLength', value=8, minimum=8, maximum=32, enabled=true, visible=true, showing=true]
          javax.swing.JPanel[name='panelDisplayedAccounts']
            javax.swing.JLabel[name=null, text='Accounts', enabled=true, visible=true, showing=false]
            javax.swing.JButton[name='buttonFindAllAccounts', text='Find All', enabled=true, visible=true, showing=false]
            javax.swing.JSeparator[,115,46,21x27,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,orientation=VERTICAL]
            javax.swing.JLabel[name=null, text='Text to FInd', enabled=true, visible=true, showing=false]
            javax.swing.JTextField[name='textFieldSearchText', text='', enabled=true, visible=true, showing=false]

javax.swing.JButton[name='buttonFindBySiteAccounts', text='Find by Site', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonFindByUsernameAccounts', text='Find By Username', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonFindByPasswordAccounts', text='Find By Password', enabled=false, visible=true, showing=false]
            javax.swing.JScrollPane[name='scrollPaneAccounts', enabled=true, visible=true, showing=false]
              javax.swing.JViewport[,1,20,928x192,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=,scrollUnderway=false]
                javax.swing.JTable[name='tableDisplayedAccounts', rowCount=0, columnCount=3, enabled=true, visible=true, showing=false]
                  javax.swing.CellRendererPane[,0,0,0x0,hidden]
              javax.swing.JScrollPane$ScrollBar[name=null, value=0, blockIncrement=10, minimum=0, maximum=0, enabled=true, visible=false, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
              javax.swing.JScrollPane$ScrollBar[name=null, value=0, blockIncrement=10, minimum=0, maximum=928, enabled=true, visible=false, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
                javax.swing.plaf.metal.MetalScrollButton[name=null, text='', enabled=true, visible=true, showing=false]
              javax.swing.JViewport[,1,1,928x19,layout=javax.swing.ViewportLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=25165832,maximumSize=,minimumSize=,preferredSize=,isViewSizeSet=true,lastPaintPosition=,scrollUnderway=false]
                javax.swing.table.JTableHeader[,0,0,928x19,alignmentX=0.0,alignmentY=0.0,border=,flags=16777544,maximumSize=,minimumSize=,preferredSize=,draggedDistance=0,reorderingAllowed=true,resizingAllowed=true,updateTableInRealTime=true]
                  javax.swing.CellRendererPane[,0,0,0x0,hidden]
            javax.swing.JButton[name='buttonDeleteAccount', text='Delete', enabled=false, visible=true, showing=false]
            javax.swing.JSeparator[,99,311,2x41,alignmentX=0.0,alignmentY=0.0,border=,flags=0,maximumSize=,minimumSize=,preferredSize=,orientation=VERTICAL]
            javax.swing.JTextField[name='textFieldUpdateCell', text='', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonModifyUsername', text='Modify Username', enabled=false, visible=true, showing=false]
            javax.swing.JButton[name='buttonModifyPassword', text='Modify Password', enabled=false, visible=true, showing=false]
            javax.swing.JLabel[name='labelOperationResult', text='', enabled=false, visible=true, showing=false]
        javax.swing.JLabel[name=null, text='Password Manager | Giulio Fagioli 6006222', enabled=true, visible=true, showing=true]
  at dev.justgiulio.passwordmanager.view.AccountSwingViewTest.testAccountIsModifiedResetTextField(AccountSwingViewTest.java:297)
JKollien commented 4 years ago

I am having similar issues on Linux!

On both matching standard components (e. g. JButton) and private component (e. g. extending JPanel) I am encountering flickering tests, meaning sometimes the error occurs and sometimes it doesn't. As well as you the component appears in the component hierarchy, what I have found here was, that for the components the tag "showing" was not present (same for you), but the Matcher had "requireShowing=true". Is this maybe causing an issue?

I am still investigating, but I would also be interested what others have to say.

Remeic commented 4 years ago

Hi @JKollien, in the initial state of my unit testing i have the same issue on macos, i solved it using

this.setVisible(true)

On my class that extends jframe, but seems "not working" on ubuntu. I'm can't figure out how fix it, i set even settings of robot to wait 500ms before check if a component is showed or not

shareof commented 3 years ago

Hi @JKollien, It`s My first Post. I have a similar event with Mr @Remeic

My Env image

In my App src

public class WFrame extends JFrame {
    protected JLabel label = null;
    protected JButton btn = null;
    protected JPanel panel =  new JPanel();

    public WFrame(String title) {
        this.setTitle(title);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setSize(300,400);
        this.setPane(getContentPane());
        this.setVisible(true);
    }

    private void setPane(Container c) {
         c.add(panel.add(getLabel()),BorderLayout.NORTH);
         c.add(panel.add(getButton()),BorderLayout.CENTER);
    }

    protected JLabel getLabel() {
        if(this.label == null) {
            this.label = new JLabel("Test");
            this.label.setText("Test");
        }
        return this.label
    }

my suite tests

package test;

import org.fest.swing.edt.FailOnThreadViolationRepaintManager;
import org.fest.swing.edt.GuiActionRunner;
import org.fest.swing.edt.GuiQuery;
import org.fest.swing.fixture.FrameFixture;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

public class WFrameTest {
    private FrameFixture mockWindow;

    @BeforeClass
    public static void beforeClass() {
        FailOnThreadViolationRepaintManager.install();
    }

    @Before
    public void before() {
        WFrame frame = GuiActionRunner.execute(new GuiQuery<WFrame>() {

            @Override
            protected WFrame executeInEDT() throws Throwable {
                return new WFrame("test app");
            }
        });

        mockWindow = new FrameFixture(frame);
        mockWindow.show();
    }

    @After
    public void after() {
        mockWindow.cleanUp();
    }

    // healthy
    @Test
    public void LabelBindDataCheckWithNoTarget() {
        mockWindow.label().text().equals("Test");
    }

    // UnHealthy
    @Test
    public void LabelBindDataCheckWithTarget() {
        mockWindow.label("Test").text().equals("Test");
    }
}

my test logs image

Is that any Plan ?