initial commit

Signed-off-by: Peter Siegmund <mars3142@noreply.mars3142.dev>
This commit is contained in:
2025-10-31 23:37:30 +01:00
commit bf6b52fd94
9654 changed files with 4035664 additions and 0 deletions

View File

@@ -0,0 +1,360 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/auitest.cpp
// Purpose: wxAui control tests
// Author: Sebastian Walderich
// Created: 2018-12-19
// Copyright: (c) 2018 Sebastian Walderich
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_AUI
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/panel.h"
#include "wx/aui/auibar.h"
#include "wx/aui/auibook.h"
#include "wx/aui/serializer.h"
#include "asserthelper.h"
#include <memory>
// ----------------------------------------------------------------------------
// test fixtures
// ----------------------------------------------------------------------------
class AuiNotebookTestCase
{
public:
AuiNotebookTestCase()
: nb(new wxAuiNotebook(wxTheApp->GetTopWindow()))
{
}
~AuiNotebookTestCase()
{
delete nb;
}
protected:
wxAuiNotebook* const nb;
};
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::DoGetBestSize", "[aui]")
{
wxPanel *p = new wxPanel(nb);
p->SetMinSize(wxSize(100, 100));
REQUIRE( nb->AddPage(p, "Center Pane") );
const int tabHeight = nb->GetTabCtrlHeight();
SECTION( "Single pane with multiple tabs" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(300, 100));
nb->AddPage(p, "Center Tab 2");
p = new wxPanel(nb);
p->SetMinSize(wxSize(100, 200));
nb->AddPage(p, "Center Tab 3");
CHECK( nb->GetBestSize() == wxSize(300, 200 + tabHeight) );
}
SECTION( "Horizontal split" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(25, 0));
nb->AddPage(p, "Left Pane");
nb->Split(nb->GetPageCount()-1, wxLEFT);
CHECK( nb->GetBestSize() == wxSize(125, 100 + tabHeight) );
p = new wxPanel(nb);
p->SetMinSize(wxSize(50, 0));
nb->AddPage(p, "Right Pane 1");
nb->Split(nb->GetPageCount()-1, wxRIGHT);
CHECK( nb->GetBestSize() == wxSize(175, 100 + tabHeight) );
p = new wxPanel(nb);
p->SetMinSize(wxSize(100, 0));
nb->AddPage(p, "Right Pane 2");
nb->Split(nb->GetPageCount()-1, wxRIGHT);
CHECK( nb->GetBestSize() == wxSize(275, 100 + tabHeight) );
}
SECTION( "Vertical split" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(0, 100));
nb->AddPage(p, "Top Pane 1");
nb->Split(nb->GetPageCount()-1, wxTOP);
p = new wxPanel(nb);
p->SetMinSize(wxSize(0, 50));
nb->AddPage(p, "Top Pane 2");
nb->Split(nb->GetPageCount()-1, wxTOP);
CHECK( nb->GetBestSize() == wxSize(100, 250 + 3*tabHeight) );
p = new wxPanel(nb);
p->SetMinSize(wxSize(0, 25));
nb->AddPage(p, "Bottom Pane");
nb->Split(nb->GetPageCount()-1, wxBOTTOM);
CHECK( nb->GetBestSize() == wxSize(100, 275 + 4*tabHeight) );
}
SECTION( "Surrounding panes" )
{
p = new wxPanel(nb);
p->SetMinSize(wxSize(50, 25));
nb->AddPage(p, "Bottom Pane");
nb->Split(nb->GetPageCount()-1, wxBOTTOM);
p = new wxPanel(nb);
p->SetMinSize(wxSize(50, 120));
nb->AddPage(p, "Right Pane");
nb->Split(nb->GetPageCount()-1, wxRIGHT);
p = new wxPanel(nb);
p->SetMinSize(wxSize(225, 50));
nb->AddPage(p, "Top Pane");
nb->Split(nb->GetPageCount()-1, wxTOP);
p = new wxPanel(nb);
p->SetMinSize(wxSize(25, 105));
nb->AddPage(p, "Left Pane");
nb->Split(nb->GetPageCount()-1, wxLEFT);
CHECK( nb->GetBestSize() == wxSize(250, 175 + 3*tabHeight) );
}
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::RTTI", "[aui][rtti]")
{
wxBookCtrlBase* const book = nb;
CHECK( wxDynamicCast(book, wxAuiNotebook) == nb );
CHECK( wxDynamicCast(nb, wxBookCtrlBase) == book );
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::FindPage", "[aui]")
{
wxPanel *p1 = new wxPanel(nb);
wxPanel *p2 = new wxPanel(nb);
wxPanel *p3 = new wxPanel(nb);
REQUIRE( nb->AddPage(p1, "Page 1") );
REQUIRE( nb->AddPage(p2, "Page 2") );
CHECK( nb->FindPage(nullptr) == wxNOT_FOUND );
CHECK( nb->FindPage(p1) == 0 );
CHECK( nb->FindPage(p2) == 1 );
CHECK( nb->FindPage(p3) == wxNOT_FOUND );
}
TEST_CASE_METHOD(AuiNotebookTestCase, "wxAuiNotebook::Layout", "[aui]")
{
const auto addPage = [this](int n)
{
return nb->AddPage(new wxPanel(nb), wxString::Format("Page %d", n + 1));
};
for ( int n = 0; n < 5; n++ )
{
REQUIRE( addPage(n) );
}
using Ints = std::vector<int>;
using Indices = std::vector<size_t>;
// This serializer allows the code below to tweak its data before using it
// as deserializer.
class TestSerializer : public wxAuiBookSerializer,
public wxAuiBookDeserializer
{
public:
virtual void BeforeSaveNotebook(const wxString& name) override
{
m_name = name;
m_afterSaveCalled = false;
m_tabsLayoutInfo.clear();
}
virtual void
SaveNotebookTabControl(const wxAuiTabLayoutInfo& tab) override
{
m_tabsLayoutInfo.push_back(tab);
}
virtual void AfterSaveNotebook() override
{
m_afterSaveCalled = true;
}
virtual std::vector<wxAuiTabLayoutInfo>
LoadNotebookTabs(const wxString& name) override
{
CHECK( name == m_name );
m_orphanedPages.clear();
return m_tabsLayoutInfo;
}
virtual bool
HandleOrphanedPage(wxAuiNotebook& WXUNUSED(book),
int page,
wxAuiTabCtrl** WXUNUSED(tabCtrl),
int* tabIndex) override
{
m_orphanedPages.push_back(page);
*tabIndex = m_orphanedPageReturnIndex;
return m_orphanedPageReturnValue;
}
wxString m_name;
std::vector<wxAuiTabLayoutInfo> m_tabsLayoutInfo;
bool m_afterSaveCalled = false;
Ints m_orphanedPages;
bool m_orphanedPageReturnValue = true;
int m_orphanedPageReturnIndex = wxNOT_FOUND;
} ser;
// Just for convenience.
auto& info = ser.m_tabsLayoutInfo;
// Check the default layout has expected representation.
nb->SaveLayout("layout", ser);
CHECK( ser.m_name == "layout" );
CHECK( ser.m_afterSaveCalled );
REQUIRE( info.size() == 1 );
CHECK( info[0].pages == Ints{} );
CHECK( info[0].pinned == Ints{} );
CHECK( info[0].active == 0 );
// Check that the active page is restored correctly.
info[0].active = 1;
nb->LoadLayout("layout", ser);
CHECK( nb->GetSelection() == 1 );
// Check that page order is serialized as expected.
auto* mainTabCtrl = nb->GetMainTabCtrl();
REQUIRE( mainTabCtrl );
CHECK( mainTabCtrl->MovePage(1, 4) );
nb->SaveLayout("layout", ser);
REQUIRE( info.size() == 1 );
CHECK( info[0].pages == Ints{0, 2, 3, 4, 1} );
// Check that pinned pages are serialized as expected.
REQUIRE( nb->SetPageKind(2, wxAuiTabKind::Pinned) );
nb->SaveLayout("layout", ser);
REQUIRE( info.size() == 1 );
// Note that pinning a page moves it in front of all other pages.
CHECK( info[0].pages == Ints{2, 0, 3, 4, 1} );
CHECK( info[0].pinned == Ints{2} );
// Check a more complicated case with both locked and pinned pages.
REQUIRE( nb->SetPageKind(4, wxAuiTabKind::Locked) );
REQUIRE( nb->SetPageKind(3, wxAuiTabKind::Pinned) );
nb->SaveLayout("layout", ser);
REQUIRE( info.size() == 1 );
// Note that pinning a page moves it in front of all other pages.
CHECK( info[0].pages == Ints{4, 2, 3, 0, 1} );
CHECK( info[0].pinned == Ints{2, 3} );
// Check that restoring existing layout after adding some pages works.
addPage(5);
addPage(6);
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{5, 6} );
// By default, orphaned pages should have been appended.
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) ==
Indices{4, 2, 3, 0, 1, 5, 6} );
// But we can change this by telling deserializer to insert them in front.
ser.m_orphanedPageReturnIndex = 0;
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{5, 6} );
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) ==
Indices{6, 5, 4, 2, 3, 0, 1} );
// Or drop them entirely.
ser.m_orphanedPageReturnValue = false;
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{5, 6} );
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) ==
Indices{4, 2, 3, 0, 1} );
// Finally, check that invalid data is handled gracefully.
info[0].active = 100;
info[0].pages = Ints{10, 0, 1, 2, 3, 4};
info[0].pinned = Ints{2, 99, 0};
nb->LoadLayout("layout", ser);
CHECK( ser.m_orphanedPages == Ints{} );
// Locked tab should have remained first.
CHECK( nb->GetPagesInDisplayOrder(mainTabCtrl) == Indices{4, 0, 1, 2, 3} );
// And selection should have been set to it because the specified value was
// invalid.
CHECK( nb->GetSelection() == 4 );
// And only tabs appearing before the normal ones can be pinned.
CHECK( nb->GetPageKind(0) == wxAuiTabKind::Pinned );
CHECK( nb->GetPageKind(1) == wxAuiTabKind::Normal );
CHECK( nb->GetPageKind(2) == wxAuiTabKind::Normal );
CHECK( nb->GetPageKind(3) == wxAuiTabKind::Normal );
CHECK( nb->GetPageKind(4) == wxAuiTabKind::Locked );
}
TEST_CASE("wxAuiToolBar::Items", "[aui][toolbar]")
{
std::unique_ptr<wxAuiToolBar> tbar{new wxAuiToolBar(wxTheApp->GetTopWindow())};
// Check that adding more toolbar elements doesn't invalidate the existing
// pointers.
auto first = tbar->AddLabel(wxID_ANY, "first");
tbar->AddLabel(wxID_ANY, "second");
CHECK( first->GetLabel() == "first" );
}
#endif

View File

@@ -0,0 +1,107 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/bitmapcomboboxtest.cpp
// Purpose: wxBitmapComboBox unit test
// Author: Steven Lamerton
// Created: 2010-07-15
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_BITMAPCOMBOBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/bmpcbox.h"
#include "wx/artprov.h"
#include "textentrytest.h"
#include "itemcontainertest.h"
#include "asserthelper.h"
class BitmapComboBoxTestCase : public TextEntryTestCase,
public ItemContainerTestCase,
public CppUnit::TestCase
{
public:
BitmapComboBoxTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxTextEntry *GetTestEntry() const override { return m_combo; }
virtual wxWindow *GetTestWindow() const override { return m_combo; }
virtual wxItemContainer *GetContainer() const override { return m_combo; }
virtual wxWindow *GetContainerWindow() const override { return m_combo; }
virtual void CheckStringSelection(const char * WXUNUSED(sel)) override
{
// do nothing here, as explained in TextEntryTestCase comment, our
// GetStringSelection() is the wxChoice, not wxTextEntry, one and there
// is no way to return the selection contents directly
}
CPPUNIT_TEST_SUITE( BitmapComboBoxTestCase );
wxTEXT_ENTRY_TESTS();
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Bitmap );
CPPUNIT_TEST_SUITE_END();
void Bitmap();
wxBitmapComboBox *m_combo;
wxDECLARE_NO_COPY_CLASS(BitmapComboBoxTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(BitmapComboBoxTestCase,
"[BitmapComboBoxTestCase][item-container]");
void BitmapComboBoxTestCase::setUp()
{
m_combo = new wxBitmapComboBox(wxTheApp->GetTopWindow(), wxID_ANY);
}
void BitmapComboBoxTestCase::tearDown()
{
wxDELETE(m_combo);
}
void BitmapComboBoxTestCase::Bitmap()
{
wxArrayString items;
items.push_back("item 0");
items.push_back("item 1");
// TODO: Add wxBitmapComboBoxBase::Append(wxArrayString )
for( unsigned int i = 0; i < items.size(); ++i )
m_combo->Append(items[i]);
CPPUNIT_ASSERT(!m_combo->GetItemBitmap(0).IsOk());
wxBitmap bitmap = wxArtProvider::GetIcon(wxART_INFORMATION, wxART_OTHER,
m_combo->FromDIP(wxSize(16, 16)));
m_combo->Append("item with bitmap", bitmap);
CPPUNIT_ASSERT(m_combo->GetItemBitmap(2).IsOk());
m_combo->Insert("item with bitmap", bitmap, 1);
CPPUNIT_ASSERT(m_combo->GetItemBitmap(1).IsOk());
m_combo->SetItemBitmap(0, bitmap);
CPPUNIT_ASSERT(m_combo->GetItemBitmap(0).IsOk());
CPPUNIT_ASSERT_EQUAL(m_combo->FromDIP(wxSize(16, 16)), m_combo->GetBitmapSize());
m_combo->SetSelection( 1 );
CPPUNIT_ASSERT_EQUAL( m_combo->GetStringSelection(), "item with bitmap" );
}
#endif //wxUSE_BITMAPCOMBOBOX

View File

@@ -0,0 +1,121 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/bitmaptogglebuttontest.cpp
// Purpose: wxBitmapToggleButton unit test
// Author: Steven Lamerton
// Created: 2010-07-17
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_TOGGLEBTN
#include "wx/tglbtn.h"
#ifdef wxHAS_BITMAPTOGGLEBUTTON
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "testableframe.h"
#include "wx/uiaction.h"
#include "wx/artprov.h"
class BitmapToggleButtonTestCase : public CppUnit::TestCase
{
public:
BitmapToggleButtonTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( BitmapToggleButtonTestCase );
WXUISIM_TEST( Click );
CPPUNIT_TEST( Value );
CPPUNIT_TEST_SUITE_END();
void Click();
void Value();
wxBitmapToggleButton* m_button;
wxDECLARE_NO_COPY_CLASS(BitmapToggleButtonTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( BitmapToggleButtonTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( BitmapToggleButtonTestCase,
"BitmapToggleButtonTestCase" );
void BitmapToggleButtonTestCase::setUp()
{
m_button = new wxBitmapToggleButton(wxTheApp->GetTopWindow(), wxID_ANY,
wxArtProvider::GetIcon(wxART_INFORMATION,
wxART_OTHER,
wxSize(32, 32)));
m_button->Update();
m_button->Refresh();
}
void BitmapToggleButtonTestCase::tearDown()
{
wxDELETE(m_button);
}
void BitmapToggleButtonTestCase::Click()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter clicked(m_button, wxEVT_TOGGLEBUTTON);
wxUIActionSimulator sim;
const wxPoint pos = m_button->GetScreenPosition();
//We move in slightly to account for window decorations
sim.MouseMove(pos + wxPoint(10, 10));
wxYield();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, clicked.GetCount());
CPPUNIT_ASSERT(m_button->GetValue());
clicked.Clear();
// Change the mouse position to prevent the second click from being
// recognized as double click.
sim.MouseMove(pos + wxPoint(20, 20));
wxYield();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, clicked.GetCount());
CPPUNIT_ASSERT(!m_button->GetValue());
#endif // wxUSE_UIACTIONSIMULATOR
}
void BitmapToggleButtonTestCase::Value()
{
EventCounter clicked(m_button, wxEVT_BUTTON);
m_button->SetValue(true);
CPPUNIT_ASSERT(m_button->GetValue());
m_button->SetValue(false);
CPPUNIT_ASSERT(!m_button->GetValue());
CPPUNIT_ASSERT_EQUAL( 0, clicked.GetCount() );
}
#endif // wxHAS_BITMAPTOGGLEBUTTON
#endif // wxUSE_TOGGLEBTN

View File

@@ -0,0 +1,176 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/bookctrlbasetest.cpp
// Purpose: wxBookCtrlBase unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_BOOKCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/artprov.h"
#include "wx/imaglist.h"
#include "wx/bookctrl.h"
#include "bookctrlbasetest.h"
#include "testableframe.h"
void BookCtrlBaseTestCase::AddPanels()
{
wxBookCtrlBase * const base = GetBase();
wxSize size(32, 32);
m_list = new wxImageList(size.x, size.y);
m_list->Add(wxArtProvider::GetIcon(wxART_INFORMATION, wxART_OTHER, size));
m_list->Add(wxArtProvider::GetIcon(wxART_QUESTION, wxART_OTHER, size));
m_list->Add(wxArtProvider::GetIcon(wxART_WARNING, wxART_OTHER, size));
base->AssignImageList(m_list);
Realize();
m_panel1 = new wxPanel(base);
m_panel2 = new wxPanel(base);
m_panel3 = new wxPanel(base);
base->AddPage(m_panel1, "Panel &1", false, 0);
base->AddPage(m_panel2, "Panel 2", false, 1);
base->AddPage(m_panel3, "Panel 3", false, 2);
}
void BookCtrlBaseTestCase::Selection()
{
wxBookCtrlBase * const base = GetBase();
base->SetSelection(0);
CPPUNIT_ASSERT_EQUAL(0, base->GetSelection());
CPPUNIT_ASSERT_EQUAL(wxStaticCast(m_panel1, wxWindow), base->GetCurrentPage());
base->AdvanceSelection(false);
CPPUNIT_ASSERT_EQUAL(2, base->GetSelection());
CPPUNIT_ASSERT_EQUAL(wxStaticCast(m_panel3, wxWindow), base->GetCurrentPage());
base->AdvanceSelection();
CPPUNIT_ASSERT_EQUAL(0, base->GetSelection());
CPPUNIT_ASSERT_EQUAL(wxStaticCast(m_panel1, wxWindow), base->GetCurrentPage());
base->ChangeSelection(1);
CPPUNIT_ASSERT_EQUAL(1, base->GetSelection());
CPPUNIT_ASSERT_EQUAL(wxStaticCast(m_panel2, wxWindow), base->GetCurrentPage());
}
void BookCtrlBaseTestCase::Text()
{
wxBookCtrlBase * const base = GetBase();
const wxString expected(HasBrokenMnemonics() ? "Panel 1" : "Panel &1");
CPPUNIT_ASSERT_EQUAL(expected, base->GetPageText(0));
base->SetPageText(1, "Some other string");
CPPUNIT_ASSERT_EQUAL("Some other string", base->GetPageText(1));
base->SetPageText(2, "string with\nline break");
CPPUNIT_ASSERT_EQUAL("string with\nline break", base->GetPageText(2));
if ( !HasBrokenMnemonics() )
{
base->SetPageText(0, "With &mnemonic");
CPPUNIT_ASSERT_EQUAL("With &mnemonic", base->GetPageText(0));
}
}
void BookCtrlBaseTestCase::PageManagement()
{
wxBookCtrlBase * const base = GetBase();
base->InsertPage(0, new wxPanel(base), "New Panel", true, 0);
Realize();
CPPUNIT_ASSERT_EQUAL(0, base->GetSelection());
CPPUNIT_ASSERT_EQUAL(4, base->GetPageCount());
// Change the selection to verify that deleting a page before the currently
// selected one correctly updates the selection.
base->SetSelection(2);
CPPUNIT_ASSERT_EQUAL(2, base->GetSelection());
base->DeletePage(1);
CPPUNIT_ASSERT_EQUAL(3, base->GetPageCount());
CPPUNIT_ASSERT_EQUAL(1, base->GetSelection());
base->RemovePage(0);
CPPUNIT_ASSERT_EQUAL(2, base->GetPageCount());
CPPUNIT_ASSERT_EQUAL(0, base->GetSelection());
base->DeleteAllPages();
CPPUNIT_ASSERT_EQUAL(0, base->GetPageCount());
CPPUNIT_ASSERT_EQUAL(-1, base->GetSelection());
}
void BookCtrlBaseTestCase::ChangeEvents()
{
wxBookCtrlBase * const base = GetBase();
base->SetSelection(0);
EventCounter changing(base, GetChangingEvent());
EventCounter changed(base, GetChangedEvent());
base->SetSelection(1);
CPPUNIT_ASSERT_EQUAL(1, changing.GetCount());
CPPUNIT_ASSERT_EQUAL(1, changed.GetCount());
changed.Clear();
changing.Clear();
base->ChangeSelection(2);
CPPUNIT_ASSERT_EQUAL(0, changing.GetCount());
CPPUNIT_ASSERT_EQUAL(0, changed.GetCount());
base->AdvanceSelection();
CPPUNIT_ASSERT_EQUAL(1, changing.GetCount());
CPPUNIT_ASSERT_EQUAL(1, changed.GetCount());
changed.Clear();
changing.Clear();
base->AdvanceSelection(false);
CPPUNIT_ASSERT_EQUAL(1, changing.GetCount());
CPPUNIT_ASSERT_EQUAL(1, changed.GetCount());
}
void BookCtrlBaseTestCase::Image()
{
wxBookCtrlBase * const base = GetBase();
//Check AddPanels() set things correctly
CPPUNIT_ASSERT_EQUAL(m_list, base->GetImageList());
CPPUNIT_ASSERT_EQUAL(0, base->GetPageImage(0));
CPPUNIT_ASSERT_EQUAL(1, base->GetPageImage(1));
CPPUNIT_ASSERT_EQUAL(2, base->GetPageImage(2));
base->SetPageImage(0, 2);
CPPUNIT_ASSERT_EQUAL(2, base->GetPageImage(2));
}
#endif

View File

@@ -0,0 +1,67 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/bookctrlbasetest.cpp
// Purpose: wxBookCtrlBase unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_TESTS_CONTROLS_BOOKCTRLBASETEST_H_
#define _WX_TESTS_CONTROLS_BOOKCTRLBASETEST_H_
class BookCtrlBaseTestCase
{
public:
BookCtrlBaseTestCase() { }
virtual ~BookCtrlBaseTestCase() { }
protected:
// this function must be overridden by the derived classes to return the
// text entry object we're testing, typically this is done by creating a
// control implementing wxBookCtrlBase interface in setUp() virtual method and
// just returning it from here
virtual wxBookCtrlBase *GetBase() const = 0;
virtual wxEventType GetChangedEvent() const = 0;
virtual wxEventType GetChangingEvent() const = 0;
// Some wxBookCtrlBase-derived classes strip mnemonics and don't return
// them from their GetPageText(), allow them to just return true from here.
virtual bool HasBrokenMnemonics() const { return false; }
// this should be inserted in the derived class CPPUNIT_TEST_SUITE
// definition to run all wxBookCtrlBase tests as part of it
#define wxBOOK_CTRL_BASE_TESTS() \
CPPUNIT_TEST( Selection ); \
CPPUNIT_TEST( Text ); \
CPPUNIT_TEST( PageManagement ); \
CPPUNIT_TEST( ChangeEvents )
void Selection();
void Text();
void PageManagement();
void ChangeEvents();
//You need to add CPPUNIT_TEST( Image ) specifically if you want it to be
//tested as only wxNotebook and wxTreebook support images correctly
void Image();
//Call this from the setUp function of a specific test to add panels to
//the ctrl.
void AddPanels();
// Override this to call Realize() on the toolbar in the wxToolbook test.
virtual void Realize() { }
wxPanel* m_panel1;
wxPanel* m_panel2;
wxPanel* m_panel3;
wxImageList* m_list;
private:
wxDECLARE_NO_COPY_CLASS(BookCtrlBaseTestCase);
};
#endif // _WX_TESTS_CONTROLS_BOOKCTRLBASETEST_H_

View File

@@ -0,0 +1,190 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/buttontest.cpp
// Purpose: wxButton unit test
// Author: Steven Lamerton
// Created: 2010-06-21
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_BUTTON
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/button.h"
#endif // WX_PRECOMP
#include "testableframe.h"
#include "wx/uiaction.h"
#include "wx/artprov.h"
// Get operator<<(wxSize) so that wxSize values are shown correctly in case of
// a failure of a CHECK() involving them.
#include "asserthelper.h"
#include "waitfor.h"
class ButtonTestCase
{
public:
ButtonTestCase();
~ButtonTestCase();
protected:
wxButton* m_button;
wxDECLARE_NO_COPY_CLASS(ButtonTestCase);
};
ButtonTestCase::ButtonTestCase()
{
//We use wxTheApp->GetTopWindow() as there is only a single testable frame
//so it will always be returned
m_button = new wxButton(wxTheApp->GetTopWindow(), wxID_ANY, "wxButton");
}
ButtonTestCase::~ButtonTestCase()
{
delete m_button;
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(ButtonTestCase, "Button::Click", "[button]")
{
//We use the internal class EventCounter which handles connecting and
//disconnecting the control to the wxTestableFrame
EventCounter clicked(m_button, wxEVT_BUTTON);
wxUIActionSimulator sim;
//We move in slightly to account for window decorations, we need to yield
//after every wxUIActionSimulator action to keep everything working in GTK
sim.MouseMove(m_button->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick();
// At least under wxMSW calling wxYield() just once doesn't always work, so
// try for a while.
WaitFor("button to be clicked", [&]() { return clicked.GetCount() != 0; });
CHECK( clicked.GetCount() == 1 );
}
TEST_CASE_METHOD(ButtonTestCase, "Button::Disabled", "[button]")
{
wxUIActionSimulator sim;
// In this test we disable the button and check events are not sent and we
// do it once by disabling the previously enabled button and once by
// creating the button in the disabled state.
SECTION("Disable after creation")
{
m_button->Disable();
}
SECTION("Create disabled")
{
delete m_button;
m_button = new wxButton();
m_button->Disable();
m_button->Create(wxTheApp->GetTopWindow(), wxID_ANY, "wxButton");
}
EventCounter clicked(m_button, wxEVT_BUTTON);
sim.MouseMove(m_button->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick();
wxYield();
CHECK( clicked.GetCount() == 0 );
}
#endif // wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(ButtonTestCase, "Button::Auth", "[button]")
{
//Some functions only work on specific operating system versions, for
//this we need a runtime check
int major = 0;
if(wxGetOsVersion(&major) != wxOS_WINDOWS_NT || major < 6)
return;
//We are running Windows Vista or newer
CHECK(!m_button->GetAuthNeeded());
m_button->SetAuthNeeded();
CHECK(m_button->GetAuthNeeded());
//We test both states
m_button->SetAuthNeeded(false);
CHECK(!m_button->GetAuthNeeded());
}
TEST_CASE_METHOD(ButtonTestCase, "Button::BitmapMargins", "[button]")
{
//Some functions only work on specific platforms in which case we can use
//a preprocessor check
#ifdef __WXMSW__
//We must set a bitmap before we can set its margins, when writing unit
//tests it is easiest to use an image from wxArtProvider
m_button->SetBitmap(wxArtProvider::GetIcon(wxART_INFORMATION, wxART_OTHER,
wxSize(32, 32)));
m_button->SetBitmapMargins(15, 15);
CHECK( m_button->GetBitmapMargins() == wxSize(15, 15) );
m_button->SetBitmapMargins(wxSize(20, 20));
CHECK( m_button->GetBitmapMargins() == wxSize(20, 20) );
#endif
}
TEST_CASE_METHOD(ButtonTestCase, "Button::Bitmap", "[button]")
{
//We start with no bitmaps
CHECK(!m_button->GetBitmap().IsOk());
// Some bitmap, doesn't really matter which.
const wxBitmap bmp = wxArtProvider::GetBitmap(wxART_INFORMATION);
m_button->SetBitmap(bmp);
CHECK(m_button->GetBitmap().IsOk());
// The call above shouldn't affect any other bitmaps as returned by the API
// even though the same (normal) bitmap does appear for all the states.
CHECK( !m_button->GetBitmapCurrent().IsOk() );
CHECK( !m_button->GetBitmapDisabled().IsOk() );
CHECK( !m_button->GetBitmapFocus().IsOk() );
CHECK( !m_button->GetBitmapPressed().IsOk() );
// Do set one of the bitmaps now.
m_button->SetBitmapPressed(wxArtProvider::GetBitmap(wxART_ERROR));
CHECK( m_button->GetBitmapPressed().IsOk() );
// Check that resetting the button label doesn't result in problems when
// updating the bitmap later, as it used to be the case in wxGTK (#18898).
m_button->SetLabel(wxString());
CHECK_NOTHROW( m_button->Disable() );
wxButton* button = new wxButton(m_button->GetParent(), wxID_ANY, "a");
button->SetLabel("");
CHECK_NOTHROW(button->SetBitmap(bmp));
delete button;
// Also check that setting an invalid bitmap doesn't do anything untoward,
// such as crashing, as it used to do in wxOSX (#19257).
CHECK_NOTHROW( m_button->SetBitmapPressed(wxNullBitmap) );
CHECK( !m_button->GetBitmapPressed().IsOk() );
}
#endif //wxUSE_BUTTON

View File

@@ -0,0 +1,168 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/checkboxtest.cpp
// Purpose: wCheckBox unit test
// Author: Steven Lamerton
// Created: 2010-07-14
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_CHECKBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/checkbox.h"
#endif // WX_PRECOMP
#include "testableframe.h"
class CheckBoxTestCase : public CppUnit::TestCase
{
public:
CheckBoxTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( CheckBoxTestCase );
CPPUNIT_TEST( Check );
#ifdef wxHAS_3STATE_CHECKBOX
CPPUNIT_TEST( ThirdState );
CPPUNIT_TEST( ThirdStateUser );
CPPUNIT_TEST( InvalidStyles );
#endif // wxHAS_3STATE_CHECKBOX
CPPUNIT_TEST_SUITE_END();
void Check();
#ifdef wxHAS_3STATE_CHECKBOX
void ThirdState();
void ThirdStateUser();
void InvalidStyles();
#endif // wxHAS_3STATE_CHECKBOX
// Initialize m_check with a new checkbox with the specified style
//
// This function always returns false just to make it more convenient to
// use inside WX_ASSERT_FAILS_WITH_ASSERT(), its return value doesn't have
// any meaning otherwise.
bool CreateCheckBox(long style)
{
wxDELETE( m_check );
m_check = new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, "Check box",
wxDefaultPosition, wxDefaultSize, style);
return false;
}
wxCheckBox* m_check;
wxDECLARE_NO_COPY_CLASS(CheckBoxTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( CheckBoxTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( CheckBoxTestCase, "CheckBoxTestCase" );
void CheckBoxTestCase::setUp()
{
m_check = new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, "Check box");
}
void CheckBoxTestCase::tearDown()
{
delete m_check;
}
void CheckBoxTestCase::Check()
{
EventCounter clicked(m_check, wxEVT_CHECKBOX);
//We should be unchecked by default
CPPUNIT_ASSERT(!m_check->IsChecked());
m_check->SetValue(true);
CPPUNIT_ASSERT(m_check->IsChecked());
m_check->SetValue(false);
CPPUNIT_ASSERT(!m_check->IsChecked());
m_check->Set3StateValue(wxCHK_CHECKED);
CPPUNIT_ASSERT(m_check->IsChecked());
m_check->Set3StateValue(wxCHK_UNCHECKED);
CPPUNIT_ASSERT(!m_check->IsChecked());
//None of these should send events
CPPUNIT_ASSERT_EQUAL(0, clicked.GetCount());
}
#ifdef wxHAS_3STATE_CHECKBOX
void CheckBoxTestCase::ThirdState()
{
CreateCheckBox(wxCHK_3STATE);
CPPUNIT_ASSERT_EQUAL(wxCHK_UNCHECKED, m_check->Get3StateValue());
CPPUNIT_ASSERT(m_check->Is3State());
CPPUNIT_ASSERT(!m_check->Is3rdStateAllowedForUser());
m_check->SetValue(true);
CPPUNIT_ASSERT_EQUAL(wxCHK_CHECKED, m_check->Get3StateValue());
m_check->Set3StateValue(wxCHK_UNDETERMINED);
CPPUNIT_ASSERT_EQUAL(wxCHK_UNDETERMINED, m_check->Get3StateValue());
}
void CheckBoxTestCase::ThirdStateUser()
{
CreateCheckBox(wxCHK_3STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER);
CPPUNIT_ASSERT_EQUAL(wxCHK_UNCHECKED, m_check->Get3StateValue());
CPPUNIT_ASSERT(m_check->Is3State());
CPPUNIT_ASSERT(m_check->Is3rdStateAllowedForUser());
m_check->SetValue(true);
CPPUNIT_ASSERT_EQUAL(wxCHK_CHECKED, m_check->Get3StateValue());
m_check->Set3StateValue(wxCHK_UNDETERMINED);
CPPUNIT_ASSERT_EQUAL(wxCHK_UNDETERMINED, m_check->Get3StateValue());
m_check->SetValue(true);
CPPUNIT_ASSERT_EQUAL(wxCHK_CHECKED, m_check->Get3StateValue());
}
void CheckBoxTestCase::InvalidStyles()
{
// Check that using incompatible styles doesn't work.
WX_ASSERT_FAILS_WITH_ASSERT( CreateCheckBox(wxCHK_2STATE | wxCHK_3STATE) );
#if !wxDEBUG_LEVEL
CPPUNIT_ASSERT( !m_check->Is3State() );
CPPUNIT_ASSERT( !m_check->Is3rdStateAllowedForUser() );
#endif
WX_ASSERT_FAILS_WITH_ASSERT(
CreateCheckBox(wxCHK_2STATE | wxCHK_ALLOW_3RD_STATE_FOR_USER) );
#if !wxDEBUG_LEVEL
CPPUNIT_ASSERT( !m_check->Is3State() );
CPPUNIT_ASSERT( !m_check->Is3rdStateAllowedForUser() );
#endif
// wxCHK_ALLOW_3RD_STATE_FOR_USER without wxCHK_3STATE doesn't work.
WX_ASSERT_FAILS_WITH_ASSERT( CreateCheckBox(wxCHK_ALLOW_3RD_STATE_FOR_USER) );
}
#endif // wxHAS_3STATE_CHECKBOX
#endif // wxUSE_CHECKBOX

View File

@@ -0,0 +1,90 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/checklistlistbox.cpp
// Purpose: wxCheckListBox unit test
// Author: Steven Lamerton
// Created: 2010-06-30
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_CHECKLISTBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/checklst.h"
#endif // WX_PRECOMP
#include "itemcontainertest.h"
#include "testableframe.h"
class CheckListBoxTestCase : public ItemContainerTestCase, public CppUnit::TestCase
{
public:
CheckListBoxTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxItemContainer *GetContainer() const override { return m_check; }
virtual wxWindow *GetContainerWindow() const override { return m_check; }
CPPUNIT_TEST_SUITE( CheckListBoxTestCase );
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Check );
CPPUNIT_TEST_SUITE_END();
void Check();
wxCheckListBox* m_check;
wxDECLARE_NO_COPY_CLASS(CheckListBoxTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(CheckListBoxTestCase,
"[CheckListBoxTestCase][item-container]");
void CheckListBoxTestCase::setUp()
{
m_check = new wxCheckListBox(wxTheApp->GetTopWindow(), wxID_ANY);
}
void CheckListBoxTestCase::tearDown()
{
wxDELETE(m_check);
}
void CheckListBoxTestCase::Check()
{
EventCounter toggled(m_check, wxEVT_CHECKLISTBOX);
wxArrayInt checkedItems;
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
testitems.Add("item 3");
m_check->Append(testitems);
m_check->Check(0);
m_check->Check(1);
m_check->Check(1, false);
//We should not get any events when changing this from code
CPPUNIT_ASSERT_EQUAL(0, toggled.GetCount());
CPPUNIT_ASSERT_EQUAL(true, m_check->IsChecked(0));
CPPUNIT_ASSERT_EQUAL(false, m_check->IsChecked(1));
CPPUNIT_ASSERT_EQUAL(1, m_check->GetCheckedItems(checkedItems));
CPPUNIT_ASSERT_EQUAL(0, checkedItems[0]);
//Make sure a double check of an items doesn't deselect it
m_check->Check(0);
CPPUNIT_ASSERT_EQUAL(true, m_check->IsChecked(0));
}
#endif // wxUSE_CHECKLISTBOX

View File

@@ -0,0 +1,79 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/choicebooktest.cpp
// Purpose: wxChoicebook unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_CHOICEBOOK
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/choicebk.h"
#include "bookctrlbasetest.h"
class ChoicebookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase
{
public:
ChoicebookTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxBookCtrlBase *GetBase() const override { return m_choicebook; }
virtual wxEventType GetChangedEvent() const override
{ return wxEVT_CHOICEBOOK_PAGE_CHANGED; }
virtual wxEventType GetChangingEvent() const override
{ return wxEVT_CHOICEBOOK_PAGE_CHANGING; }
virtual bool HasBrokenMnemonics() const override { return true; }
CPPUNIT_TEST_SUITE( ChoicebookTestCase );
wxBOOK_CTRL_BASE_TESTS();
CPPUNIT_TEST( Choice );
CPPUNIT_TEST_SUITE_END();
void Choice();
wxChoicebook *m_choicebook;
wxDECLARE_NO_COPY_CLASS(ChoicebookTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( ChoicebookTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ChoicebookTestCase, "ChoicebookTestCase" );
void ChoicebookTestCase::setUp()
{
m_choicebook = new wxChoicebook(wxTheApp->GetTopWindow(), wxID_ANY);
AddPanels();
}
void ChoicebookTestCase::tearDown()
{
wxDELETE(m_choicebook);
}
void ChoicebookTestCase::Choice()
{
wxChoice* choice = m_choicebook->GetChoiceCtrl();
CPPUNIT_ASSERT(choice);
CPPUNIT_ASSERT_EQUAL(3, choice->GetCount());
CPPUNIT_ASSERT_EQUAL("Panel 1", choice->GetString(0));
}
#endif //wxUSE_CHOICEBOOK

View File

@@ -0,0 +1,120 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/choice.cpp
// Purpose: wxChoice unit test
// Author: Steven Lamerton
// Created: 2010-06-29
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_CHOICE
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/choice.h"
#endif // WX_PRECOMP
#include "itemcontainertest.h"
class ChoiceTestCase : public ItemContainerTestCase, public CppUnit::TestCase
{
public:
ChoiceTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxItemContainer *GetContainer() const override { return m_choice; }
virtual wxWindow *GetContainerWindow() const override { return m_choice; }
CPPUNIT_TEST_SUITE( ChoiceTestCase );
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Sort );
CPPUNIT_TEST( GetBestSize );
CPPUNIT_TEST_SUITE_END();
void Sort();
void GetBestSize();
wxChoice* m_choice;
wxDECLARE_NO_COPY_CLASS(ChoiceTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(ChoiceTestCase,
"[ChoiceTestCase][item-container]");
void ChoiceTestCase::setUp()
{
m_choice = new wxChoice(wxTheApp->GetTopWindow(), wxID_ANY);
}
void ChoiceTestCase::tearDown()
{
wxDELETE(m_choice);
}
void ChoiceTestCase::Sort()
{
#if !defined(__WXOSX__)
wxDELETE(m_choice);
m_choice = new wxChoice(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize, 0, nullptr,
wxCB_SORT);
wxArrayString testitems;
testitems.Add("aaa");
testitems.Add("Aaa");
testitems.Add("aba");
testitems.Add("aaab");
testitems.Add("aab");
testitems.Add("AAA");
m_choice->Append(testitems);
CPPUNIT_ASSERT_EQUAL("AAA", m_choice->GetString(0));
CPPUNIT_ASSERT_EQUAL("Aaa", m_choice->GetString(1));
CPPUNIT_ASSERT_EQUAL("aaa", m_choice->GetString(2));
CPPUNIT_ASSERT_EQUAL("aaab", m_choice->GetString(3));
CPPUNIT_ASSERT_EQUAL("aab", m_choice->GetString(4));
CPPUNIT_ASSERT_EQUAL("aba", m_choice->GetString(5));
m_choice->Append("a");
CPPUNIT_ASSERT_EQUAL("a", m_choice->GetString(0));
#endif
}
void ChoiceTestCase::GetBestSize()
{
wxArrayString testitems;
testitems.Add("1");
testitems.Add("11");
m_choice->Append(testitems);
SECTION("Normal best size")
{
// nothing to do here
}
// Ensure that the hidden control return a valid best size too.
SECTION("Hidden best size")
{
m_choice->Hide();
}
wxYield();
m_choice->InvalidateBestSize();
const wxSize bestSize = m_choice->GetBestSize();
CHECK(bestSize.GetWidth() > m_choice->FromDIP(30));
CHECK(bestSize.GetWidth() < m_choice->FromDIP(120));
CHECK(bestSize.GetHeight() > m_choice->FromDIP(15));
CHECK(bestSize.GetHeight() < m_choice->FromDIP(35));
}
#endif //wxUSE_CHOICE

View File

@@ -0,0 +1,273 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/comboboxtest.cpp
// Purpose: wxComboBox unit test
// Author: Vadim Zeitlin
// Created: 2007-09-25
// Copyright: (c) 2007 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_COMBOBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/combobox.h"
#endif // WX_PRECOMP
#include "textentrytest.h"
#include "itemcontainertest.h"
#include "testableframe.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class ComboBoxTestCase : public TextEntryTestCase, public ItemContainerTestCase,
public CppUnit::TestCase
{
public:
ComboBoxTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxTextEntry *GetTestEntry() const override { return m_combo; }
virtual wxWindow *GetTestWindow() const override { return m_combo; }
virtual wxItemContainer *GetContainer() const override { return m_combo; }
virtual wxWindow *GetContainerWindow() const override { return m_combo; }
virtual void CheckStringSelection(const char * WXUNUSED(sel)) override
{
// do nothing here, as explained in TextEntryTestCase comment, our
// GetStringSelection() is the wxChoice, not wxTextEntry, one and there
// is no way to return the selection contents directly
}
CPPUNIT_TEST_SUITE( ComboBoxTestCase );
#ifdef __WXOSX__
CPPUNIT_TEST( SetValue );
CPPUNIT_TEST( TextChangeEvents );
CPPUNIT_TEST( Selection );
CPPUNIT_TEST( InsertionPoint );
CPPUNIT_TEST( Replace );
// TODO on OS X only works interactively
// WXUISIM_TEST( Editable );
CPPUNIT_TEST( Hint );
CPPUNIT_TEST( CopyPaste );
CPPUNIT_TEST( UndoRedo );
#else
wxTEXT_ENTRY_TESTS();
#endif
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Size );
CPPUNIT_TEST( PopDismiss );
CPPUNIT_TEST( Sort );
CPPUNIT_TEST( ReadOnly );
CPPUNIT_TEST( IsEmpty );
CPPUNIT_TEST( SetStringSelection );
CPPUNIT_TEST_SUITE_END();
void Size();
void PopDismiss();
void Sort();
void ReadOnly();
void IsEmpty();
void SetStringSelection();
wxComboBox *m_combo;
wxDECLARE_NO_COPY_CLASS(ComboBoxTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(ComboBoxTestCase,
"[ComboBoxTestCase][item-container]");
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void ComboBoxTestCase::setUp()
{
m_combo = new wxComboBox(wxTheApp->GetTopWindow(), wxID_ANY);
}
void ComboBoxTestCase::tearDown()
{
delete m_combo;
m_combo = nullptr;
}
// ----------------------------------------------------------------------------
// tests themselves
// ----------------------------------------------------------------------------
void ComboBoxTestCase::Size()
{
// under MSW changing combobox size is a non-trivial operation because of
// confusion between the size of the control with and without dropdown, so
// check that it does work as expected
const int heightOrig = m_combo->GetSize().y;
// check that the height doesn't change if we don't touch it
m_combo->SetSize(100, -1);
CPPUNIT_ASSERT_EQUAL( heightOrig, m_combo->GetSize().y );
// check that setting both big and small (but not too small, there is a
// limit on how small the control can become under MSW) heights works
m_combo->SetSize(-1, 50);
CPPUNIT_ASSERT_EQUAL( 50, m_combo->GetSize().y );
m_combo->SetSize(-1, 10);
CPPUNIT_ASSERT_EQUAL( 10, m_combo->GetSize().y );
// and also that restoring it works (this used to be broken before 2.9.1)
m_combo->SetSize(-1, heightOrig);
CPPUNIT_ASSERT_EQUAL( heightOrig, m_combo->GetSize().y );
}
void ComboBoxTestCase::PopDismiss()
{
#if defined(__WXMSW__) || defined(__WXGTK210__) || defined(__WXQT__)
EventCounter drop(m_combo, wxEVT_COMBOBOX_DROPDOWN);
EventCounter close(m_combo, wxEVT_COMBOBOX_CLOSEUP);
m_combo->Popup();
CPPUNIT_ASSERT_EQUAL(1, drop.GetCount());
m_combo->Dismiss();
#if defined(__WXGTK__) && !defined(__WXGTK3__)
// Under wxGTK2, the event is sent only during idle time and not
// immediately, so we need this yield to get it.
wxYield();
#endif // wxGTK2
CPPUNIT_ASSERT_EQUAL(1, close.GetCount());
#endif
}
void ComboBoxTestCase::Sort()
{
#if !defined(__WXOSX__)
delete m_combo;
m_combo = new wxComboBox(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0, nullptr,
wxCB_SORT);
m_combo->Append("aaa");
m_combo->Append("Aaa");
m_combo->Append("aba");
m_combo->Append("aaab");
m_combo->Append("aab");
m_combo->Append("AAA");
CPPUNIT_ASSERT_EQUAL("AAA", m_combo->GetString(0));
CPPUNIT_ASSERT_EQUAL("Aaa", m_combo->GetString(1));
CPPUNIT_ASSERT_EQUAL("aaa", m_combo->GetString(2));
CPPUNIT_ASSERT_EQUAL("aaab", m_combo->GetString(3));
CPPUNIT_ASSERT_EQUAL("aab", m_combo->GetString(4));
CPPUNIT_ASSERT_EQUAL("aba", m_combo->GetString(5));
m_combo->Append("a");
CPPUNIT_ASSERT_EQUAL("a", m_combo->GetString(0));
#endif
}
void ComboBoxTestCase::ReadOnly()
{
wxArrayString testitems;
testitems.Add("item 1");
testitems.Add("item 2");
delete m_combo;
m_combo = new wxComboBox(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, testitems,
wxCB_READONLY);
m_combo->SetValue("item 1");
CPPUNIT_ASSERT_EQUAL("item 1", m_combo->GetValue());
m_combo->SetValue("not an item");
CPPUNIT_ASSERT_EQUAL("item 1", m_combo->GetValue());
// Since this uses FindString it is case insensitive
m_combo->SetValue("ITEM 2");
CPPUNIT_ASSERT_EQUAL("item 2", m_combo->GetValue());
}
void ComboBoxTestCase::IsEmpty()
{
CPPUNIT_ASSERT( m_combo->IsListEmpty() );
CPPUNIT_ASSERT( m_combo->IsTextEmpty() );
m_combo->Append("foo");
CPPUNIT_ASSERT( !m_combo->IsListEmpty() );
CPPUNIT_ASSERT( m_combo->IsTextEmpty() );
m_combo->SetValue("bar");
CPPUNIT_ASSERT( !m_combo->IsListEmpty() );
CPPUNIT_ASSERT( !m_combo->IsTextEmpty() );
m_combo->Clear();
CPPUNIT_ASSERT( m_combo->IsListEmpty() );
CPPUNIT_ASSERT( m_combo->IsTextEmpty() );
#ifdef TEST_INVALID_COMBOBOX_ISEMPTY
// Compiling this should fail, see failtest target definition in test.bkl.
m_combo->IsEmpty();
#endif
}
void ComboBoxTestCase::SetStringSelection()
{
m_combo->Append("foo");
m_combo->Append("bar");
m_combo->Append("baz");
EventCounter events(m_combo, wxEVT_COMBOBOX);
m_combo->SetStringSelection("bar");
CPPUNIT_ASSERT_EQUAL( 0, events.GetCount() );
m_combo->SetStringSelection("foo");
CPPUNIT_ASSERT_EQUAL( 0, events.GetCount() );
}
TEST_CASE("wxComboBox::ProcessEnter", "[wxComboBox][enter]")
{
class ComboBoxCreator : public TextLikeControlCreator
{
public:
virtual wxControl* Create(wxWindow* parent, int style) const override
{
const wxString choices[] = { "foo", "bar", "baz" };
return new wxComboBox(parent, wxID_ANY, wxString(),
wxDefaultPosition, wxDefaultSize,
WXSIZEOF(choices), choices,
style);
}
};
TestProcessEnter(ComboBoxCreator());
}
#else
#ifdef TEST_INVALID_COMBOBOX_ISEMPTY
#error provoke failing here
#endif
#endif //wxUSE_COMBOBOX

View File

@@ -0,0 +1,887 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/dataviewctrltest.cpp
// Purpose: wxDataViewCtrl unit test
// Author: Vaclav Slavik
// Created: 2011-08-08
// Copyright: (c) 2011 Vaclav Slavik <vslavik@gmail.com>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_DATAVIEWCTRL
#include "wx/app.h"
#include "wx/dataview.h"
#include "wx/uiaction.h"
#ifdef __WXGTK__
#include "waitfor.h"
#endif // __WXGTK__
#include "testableframe.h"
#include "asserthelper.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class DataViewCtrlTestCase
{
public:
explicit DataViewCtrlTestCase(long style);
~DataViewCtrlTestCase();
protected:
void TestSelectionFor0and1();
// the dataview control itself
wxDataViewTreeCtrl *m_dvc;
// and some of its items
wxDataViewItem m_root,
m_child1,
m_child2,
m_grandchild;
wxDECLARE_NO_COPY_CLASS(DataViewCtrlTestCase);
};
class SingleSelectDataViewCtrlTestCase : public DataViewCtrlTestCase
{
public:
SingleSelectDataViewCtrlTestCase()
: DataViewCtrlTestCase(wxDV_SINGLE)
{
}
};
class MultiSelectDataViewCtrlTestCase : public DataViewCtrlTestCase
{
public:
MultiSelectDataViewCtrlTestCase()
: DataViewCtrlTestCase(wxDV_MULTIPLE)
{
}
};
class MultiColumnsDataViewCtrlTestCase
{
public:
MultiColumnsDataViewCtrlTestCase();
~MultiColumnsDataViewCtrlTestCase();
protected:
// the dataview control itself
wxDataViewListCtrl *m_dvc;
// constants
const wxSize m_size;
const int m_firstColumnWidth;
// and the columns
wxDataViewColumn* m_firstColumn;
wxDataViewColumn* m_lastColumn;
wxDECLARE_NO_COPY_CLASS(MultiColumnsDataViewCtrlTestCase);
};
class DataViewCtrlTestModel: public wxDataViewModel
{
public:
// Items of the model.
//
// wxTEST_ITEM_NULL
// |
// |-- wxTEST_ITEM_ROOT
// |
// |-- wxTEST_ITEM_CHILD
// |
// |-- wxTEST_ITEM_GRANDCHILD
// | |
// | |-- wxTEST_ITEM_LEAF
// | |
// | |-- wxTEST_ITEM_LEAF_HIDDEN
// |
// |-- wxTEST_ITEM_GRANDCHILD_HIDDEN
//
enum wxTestItem
{
wxTEST_ITEM_NULL,
wxTEST_ITEM_ROOT,
wxTEST_ITEM_CHILD,
wxTEST_ITEM_GRANDCHILD,
wxTEST_ITEM_LEAF,
wxTEST_ITEM_LEAF_HIDDEN,
wxTEST_ITEM_GRANDCHILD_HIDDEN
};
DataViewCtrlTestModel()
: m_root(wxTEST_ITEM_ROOT),
m_child(wxTEST_ITEM_CHILD),
m_grandChild(wxTEST_ITEM_GRANDCHILD),
m_leaf(wxTEST_ITEM_LEAF),
m_leafHidden(wxTEST_ITEM_LEAF_HIDDEN),
m_grandchildHidden(wxTEST_ITEM_GRANDCHILD_HIDDEN),
m_allItemsVisible(false)
{
}
wxDataViewItem GetDataViewItem(wxTestItem item) const
{
switch( item )
{
case wxTEST_ITEM_NULL:
return wxDataViewItem();
case wxTEST_ITEM_ROOT:
return wxDataViewItem(const_cast<wxTestItem*>(&m_root));
case wxTEST_ITEM_CHILD:
return wxDataViewItem(const_cast<wxTestItem*>(&m_child));
case wxTEST_ITEM_GRANDCHILD:
return wxDataViewItem(const_cast<wxTestItem*>(&m_grandChild));
case wxTEST_ITEM_LEAF:
return wxDataViewItem(const_cast<wxTestItem*>(&m_leaf));
case wxTEST_ITEM_LEAF_HIDDEN:
return wxDataViewItem(const_cast<wxTestItem*>(&m_leafHidden));
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
return wxDataViewItem(const_cast<wxTestItem*>(&m_grandchildHidden));
}
return wxDataViewItem();
}
// Overridden wxDataViewModel methods.
void GetValue(wxVariant &variant, const wxDataViewItem &item,
unsigned int WXUNUSED(col)) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
break;
case wxTEST_ITEM_ROOT:
variant = "root";
break;
case wxTEST_ITEM_CHILD:
variant = "child";
break;
case wxTEST_ITEM_GRANDCHILD:
variant = "grand child";
break;
case wxTEST_ITEM_LEAF:
variant = "leaf";
break;
case wxTEST_ITEM_LEAF_HIDDEN:
variant = "initially hidden leaf";
break;
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
variant = "initially hidden";
break;
}
}
bool SetValue(const wxVariant &WXUNUSED(variant),
const wxDataViewItem &WXUNUSED(item),
unsigned int WXUNUSED(col)) override
{
return false;
}
bool HasContainerColumns(const wxDataViewItem &WXUNUSED(item)) const override
{
// Always display all the columns, even for the containers.
return true;
}
wxDataViewItem GetParent(const wxDataViewItem &item) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
FAIL( "The item is the top most container" );
return wxDataViewItem();
case wxTEST_ITEM_ROOT:
return wxDataViewItem();
case wxTEST_ITEM_CHILD:
return GetDataViewItem(m_root);
case wxTEST_ITEM_GRANDCHILD:
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
return GetDataViewItem(m_child);
case wxTEST_ITEM_LEAF:
case wxTEST_ITEM_LEAF_HIDDEN:
return GetDataViewItem(m_grandChild);
}
return wxDataViewItem();
}
bool IsContainer(const wxDataViewItem &item) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
case wxTEST_ITEM_ROOT:
case wxTEST_ITEM_CHILD:
case wxTEST_ITEM_GRANDCHILD:
return true;
case wxTEST_ITEM_LEAF:
case wxTEST_ITEM_LEAF_HIDDEN:
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
return false;
}
return false;
}
unsigned int GetChildren(const wxDataViewItem &item,
wxDataViewItemArray &children) const override
{
switch( GetItemID(item) )
{
case wxTEST_ITEM_NULL:
children.push_back(GetDataViewItem(m_root));
return 1;
case wxTEST_ITEM_ROOT:
children.push_back(GetDataViewItem(m_child));
return 1;
case wxTEST_ITEM_CHILD:
children.push_back(GetDataViewItem(m_grandChild));
if ( m_allItemsVisible )
{
children.push_back(GetDataViewItem(m_grandchildHidden));
return 2;
}
return 1;
case wxTEST_ITEM_GRANDCHILD:
children.push_back(GetDataViewItem(m_leaf));
if ( m_allItemsVisible )
{
children.push_back(GetDataViewItem(m_leafHidden));
return 2;
}
return 1;
case wxTEST_ITEM_LEAF:
case wxTEST_ITEM_LEAF_HIDDEN:
case wxTEST_ITEM_GRANDCHILD_HIDDEN:
FAIL( "The item is not a container" );
return 0;
}
return 0;
}
enum wxItemsOrder
{
wxORDER_LEAF_THEN_GRANCHILD,
wxORDER_GRANCHILD_THEN_LEAF
};
void ShowChildren(wxItemsOrder order)
{
m_allItemsVisible = true;
switch ( order )
{
case wxORDER_LEAF_THEN_GRANCHILD:
ItemAdded(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden));
ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden));
break;
case wxORDER_GRANCHILD_THEN_LEAF:
ItemAdded(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden));
ItemAdded(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden));
break;
}
}
void HideChildren()
{
m_allItemsVisible = false;
ItemDeleted(GetDataViewItem(m_grandChild), GetDataViewItem(m_leafHidden));
ItemDeleted(GetDataViewItem(m_child), GetDataViewItem(m_grandchildHidden));
}
private:
wxTestItem GetItemID(const wxDataViewItem &dataViewItem) const
{
if ( dataViewItem.GetID() == nullptr )
return wxTEST_ITEM_NULL;
return *static_cast<wxTestItem*>(dataViewItem.GetID());
}
wxTestItem m_root;
wxTestItem m_child;
wxTestItem m_grandChild;
wxTestItem m_leaf;
wxTestItem m_leafHidden;
wxTestItem m_grandchildHidden;
// Whether wxTEST_ITEM_GRANDCHILD_HIDDEN item should be visible or not.
bool m_allItemsVisible;
};
class DataViewCtrlWithCustomModelTestCase
{
public:
DataViewCtrlWithCustomModelTestCase();
~DataViewCtrlWithCustomModelTestCase();
protected:
enum wxItemExistence
{
wxITEM_APPEAR,
wxITEM_DISAPPEAR
};
void UpdateAndWaitForItem(const wxDataViewItem& item, wxItemExistence existence)
{
m_dvc->Refresh();
m_dvc->Update();
#ifdef __WXGTK__
// Unfortunately it's not enough to call wxYield() once, so wait up to
// 0.5 sec.
WaitFor("wxDataViewCtrl upder", [this, item, existence]() {
const bool isItemRectEmpty = m_dvc->GetItemRect(item).IsEmpty();
switch ( existence )
{
case wxITEM_APPEAR:
if ( !isItemRectEmpty )
return true;
break;
case wxITEM_DISAPPEAR:
if ( isItemRectEmpty )
return true;
break;
}
return false;
});
#else // !__WXGTK__
wxUnusedVar(item);
wxUnusedVar(existence);
#endif // __WXGTK__
}
// The dataview control.
wxDataViewCtrl *m_dvc;
// The dataview model.
DataViewCtrlTestModel *m_model;
// Its items.
wxDataViewItem m_root,
m_child,
m_grandchild,
m_leaf,
m_leafHidden,
m_grandchildHidden;
wxDECLARE_NO_COPY_CLASS(DataViewCtrlWithCustomModelTestCase);
};
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
DataViewCtrlTestCase::DataViewCtrlTestCase(long style)
{
m_dvc = new wxDataViewTreeCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
wxDefaultPosition,
wxSize(400, 200),
style);
m_root = m_dvc->AppendContainer(wxDataViewItem(), "The root");
m_child1 = m_dvc->AppendContainer(m_root, "child1");
m_grandchild = m_dvc->AppendItem(m_child1, "grandchild");
m_child2 = m_dvc->AppendItem(m_root, "child2");
m_dvc->Layout();
m_dvc->Expand(m_root);
m_dvc->Refresh();
m_dvc->Update();
}
DataViewCtrlTestCase::~DataViewCtrlTestCase()
{
delete m_dvc;
}
MultiColumnsDataViewCtrlTestCase::MultiColumnsDataViewCtrlTestCase()
: m_size(200, 100),
m_firstColumnWidth(50)
{
m_dvc = new wxDataViewListCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
m_firstColumn =
m_dvc->AppendTextColumn(wxString(), wxDATAVIEW_CELL_INERT, m_firstColumnWidth);
m_lastColumn =
m_dvc->AppendTextColumn(wxString(), wxDATAVIEW_CELL_INERT);
// Set size after columns appending to extend size of the last column.
m_dvc->SetSize(m_size);
m_dvc->Layout();
m_dvc->Refresh();
m_dvc->Update();
}
MultiColumnsDataViewCtrlTestCase::~MultiColumnsDataViewCtrlTestCase()
{
delete m_dvc;
}
DataViewCtrlWithCustomModelTestCase::DataViewCtrlWithCustomModelTestCase()
{
m_dvc = new wxDataViewCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
wxDefaultPosition,
wxSize(400, 200),
wxDV_SINGLE);
m_model = new DataViewCtrlTestModel();
m_dvc->AssociateModel(m_model);
m_model->DecRef();
m_dvc->AppendColumn(
new wxDataViewColumn(
"Value",
new wxDataViewTextRenderer("string", wxDATAVIEW_CELL_INERT),
0,
m_dvc->FromDIP(200),
wxALIGN_LEFT,
wxDATAVIEW_COL_RESIZABLE));
m_root = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_ROOT);
m_child = m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_CHILD);
m_grandchild =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD);
m_leaf =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_LEAF);
m_leafHidden =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_LEAF_HIDDEN);
m_grandchildHidden =
m_model->GetDataViewItem(DataViewCtrlTestModel::wxTEST_ITEM_GRANDCHILD_HIDDEN);
m_dvc->Layout();
m_dvc->Expand(m_root);
m_dvc->Refresh();
m_dvc->Update();
}
DataViewCtrlWithCustomModelTestCase::~DataViewCtrlWithCustomModelTestCase()
{
delete m_dvc;
}
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::Selection",
"[wxDataViewCtrl][select]")
{
// Check selection round-trip.
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
REQUIRE_NOTHROW( m_dvc->SetSelections(sel) );
wxDataViewItemArray sel2;
CHECK( m_dvc->GetSelections(sel2) == wxSsize(sel) );
CHECK( sel2 == sel );
// Invalid items in GetSelections() input are supposed to be just skipped.
sel.clear();
sel.push_back(wxDataViewItem());
REQUIRE_NOTHROW( m_dvc->SetSelections(sel) );
CHECK( m_dvc->GetSelections(sel2) == 0 );
CHECK( sel2.empty() );
}
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::DeleteSelected",
"[wxDataViewCtrl][delete]")
{
#ifdef __WXGTK__
wxString useASAN;
if ( wxGetEnv("wxUSE_ASAN", &useASAN) && useASAN == "1" )
{
WARN("Skipping test resulting in a memory leak report with wxGTK");
return;
}
#endif // __WXGTK__
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
sel.push_back(m_child2);
m_dvc->SetSelections(sel);
// delete a selected item
m_dvc->DeleteItem(m_child1);
m_dvc->GetSelections(sel);
// m_child1 and its children should be removed from the selection now
REQUIRE( sel.size() == 1 );
CHECK( sel[0] == m_child2 );
}
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::DeleteNotSelected",
"[wxDataViewCtrl][delete]")
{
// TODO not working on OS X as expected
#ifdef __WXOSX__
WARN("Disabled under MacOS because this test currently fails");
#else
wxDataViewItemArray sel;
sel.push_back(m_child1);
sel.push_back(m_grandchild);
m_dvc->SetSelections(sel);
// delete unselected item
m_dvc->DeleteItem(m_child2);
m_dvc->GetSelections(sel);
// m_child1 and its children should be unaffected
REQUIRE( sel.size() == 2 );
CHECK( sel[0] == m_child1 );
CHECK( sel[1] == m_grandchild );
#endif
}
void DataViewCtrlTestCase::TestSelectionFor0and1()
{
wxDataViewItemArray selections;
// Initially there is no selection.
CHECK( m_dvc->GetSelectedItemsCount() == 0 );
CHECK( !m_dvc->HasSelection() );
CHECK( !m_dvc->GetSelection().IsOk() );
CHECK( !m_dvc->GetSelections(selections) );
CHECK( selections.empty() );
// Select one item.
m_dvc->Select(m_child1);
CHECK( m_dvc->GetSelectedItemsCount() == 1 );
CHECK( m_dvc->HasSelection() );
CHECK( m_dvc->GetSelection().IsOk() );
REQUIRE( m_dvc->GetSelections(selections) == 1 );
CHECK( selections[0] == m_child1 );
}
TEST_CASE_METHOD(MultiSelectDataViewCtrlTestCase,
"wxDVC::GetSelectionForMulti",
"[wxDataViewCtrl][select]")
{
wxDataViewItemArray selections;
TestSelectionFor0and1();
m_dvc->Select(m_child2);
CHECK( m_dvc->GetSelectedItemsCount() == 2 );
CHECK( m_dvc->HasSelection() );
CHECK( !m_dvc->GetSelection().IsOk() );
REQUIRE( m_dvc->GetSelections(selections) == 2 );
CHECK( selections[1] == m_child2 );
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::SingleSelection",
"[wxDataViewCtrl][selection]")
{
TestSelectionFor0and1();
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::IsExpanded",
"[wxDataViewCtrl][expand]")
{
CHECK( m_dvc->IsExpanded(m_root) );
CHECK( !m_dvc->IsExpanded(m_child1) );
// No idea why, but the native NSOutlineView isItemExpanded: method returns
// true for this item for some reason.
#ifdef __WXOSX__
WARN("Disabled under MacOS: IsExpanded() returns true for grand child");
#else
CHECK( !m_dvc->IsExpanded(m_grandchild) );
#endif
CHECK( !m_dvc->IsExpanded(m_child2) );
m_dvc->Collapse(m_root);
CHECK( !m_dvc->IsExpanded(m_root) );
m_dvc->ExpandChildren(m_root);
CHECK( m_dvc->IsExpanded(m_root) );
CHECK( m_dvc->IsExpanded(m_child1) );
// Expanding an already expanded node must still expand all its children.
m_dvc->Collapse(m_child1);
CHECK( !m_dvc->IsExpanded(m_child1) );
m_dvc->ExpandChildren(m_root);
CHECK( m_dvc->IsExpanded(m_child1) );
}
TEST_CASE_METHOD(DataViewCtrlWithCustomModelTestCase,
"wxDVC::Expand",
"[wxDataViewCtrl][expand]")
{
CHECK( m_dvc->IsExpanded(m_root) );
CHECK( !m_dvc->IsExpanded(m_child) );
#ifdef __WXGTK__
// We need to let the native control have some events to lay itself out.
wxYield();
#endif // __WXGTK__
// Unfortunately we can't combine test options with SECTION() so use
// the additional enum variable.
enum
{
wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD,
wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD,
wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF,
wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF
} options wxDUMMY_INITIALIZE(wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD);
SECTION( "Was Expanded, Add The Leaf Then The Grandchild" )
{
options = wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD;
}
SECTION( "Was Not Expanded, Add The Leaf Then The Grandchild" )
{
options = wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD;
}
SECTION( "Was Expanded, Add The Grandchild Then The Leaf" )
{
options = wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF;
}
SECTION( "Was Not Expanded, Add The Grandchild Then The Leaf" )
{
options = wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF;
}
switch ( options )
{
case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD:
case wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF:
CHECK( m_dvc->GetItemRect(m_grandchild).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
m_dvc->Expand(m_child);
m_dvc->Expand(m_grandchild);
UpdateAndWaitForItem(m_grandchild, wxITEM_APPEAR);
CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
m_dvc->Collapse(m_grandchild);
m_dvc->Collapse(m_child);
break;
case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD:
case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF:
// Do nothing.
break;
}
// Check wxDataViewModel::ItemAdded().
switch ( options )
{
case wxOPTIONS_EXPAND_ADD_LEAF_THEN_GRANCHILD:
case wxOPTIONS_DONT_EXPAND_ADD_LEAF_THEN_GRANCHILD:
m_model->ShowChildren(DataViewCtrlTestModel::wxORDER_LEAF_THEN_GRANCHILD);
break;
case wxOPTIONS_EXPAND_ADD_GRANCHILD_THEN_LEAF:
case wxOPTIONS_DONT_EXPAND_ADD_GRANCHILD_THEN_LEAF:
m_model->ShowChildren(DataViewCtrlTestModel::wxORDER_GRANCHILD_THEN_LEAF);
break;
}
m_dvc->Expand(m_child);
m_dvc->Expand(m_grandchild);
UpdateAndWaitForItem(m_leaf, wxITEM_APPEAR);
CHECK( m_dvc->IsExpanded(m_child) );
CHECK( m_dvc->IsExpanded(m_grandchild) );
CHECK( !m_dvc->GetItemRect(m_grandchild).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_leaf).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
CHECK( !m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
m_model->HideChildren();
UpdateAndWaitForItem(m_leafHidden, wxITEM_DISAPPEAR);
CHECK( m_dvc->GetItemRect(m_leafHidden).IsEmpty() );
// Check that the problem with nodes duplication in ItemAdded() fixed.
CHECK( m_dvc->GetItemRect(m_grandchildHidden).IsEmpty() );
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::GetItemRect",
"[wxDataViewCtrl][item]")
{
#ifdef __WXGTK__
// We need to let the native control have some events to lay itself out.
wxYield();
#endif // __WXGTK__
const wxRect rect1 = m_dvc->GetItemRect(m_child1);
const wxRect rect2 = m_dvc->GetItemRect(m_child2);
CHECK( rect1 != wxRect() );
CHECK( rect2 != wxRect() );
CHECK( rect1.x == rect2.x );
CHECK( rect1.width == rect2.width );
CHECK( rect1.height == rect2.height );
{
INFO("First child: " << rect1 << ", second one: " << rect2);
CHECK( rect1.y < rect2.y );
}
// This forces generic implementation to add m_grandchild to the tree, as
// it does it only on demand. We want the item to really be there to check
// that GetItemRect() returns an empty rectangle for collapsed items.
m_dvc->Expand(m_child1);
m_dvc->Collapse(m_child1);
const wxRect rectNotShown = m_dvc->GetItemRect(m_grandchild);
CHECK( rectNotShown == wxRect() );
// Append enough items to make the window scrollable.
for ( int i = 3; i < 100; ++i )
m_dvc->AppendItem(m_root, wxString::Format("child%d", i));
const wxDataViewItem last = m_dvc->AppendItem(m_root, "last");
// This should scroll the window to bring this item into view.
m_dvc->EnsureVisible(last);
#ifdef __WXGTK__
// Wait for the list control to be relaid out.
WaitFor("wxDataViewCtrl layout", [this]() {
return m_dvc->GetTopItem() != m_root;
});
#endif // __WXGTK__
// Check that this was indeed the case.
const wxDataViewItem top = m_dvc->GetTopItem();
CHECK( top != m_root );
// Verify that the coordinates are returned in physical coordinates of the
// window and not the logical coordinates affected by scrolling.
const wxRect rectScrolled = m_dvc->GetItemRect(top);
CHECK( rectScrolled.GetBottom() > 0 );
CHECK( rectScrolled.GetTop() <= m_dvc->GetClientSize().y );
// Also check that the root item is not currently visible (because it's
// scrolled off).
const wxRect rectRoot = m_dvc->GetItemRect(m_root);
CHECK( rectRoot == wxRect() );
}
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::DeleteAllItems",
"[wxDataViewCtrl][delete]")
{
// The invalid item corresponds to the root of tree store model, so it
// should have a single item (our m_root) initially.
CHECK( m_dvc->GetChildCount(wxDataViewItem()) == 1 );
m_dvc->DeleteAllItems();
// And none at all after deleting all the items.
CHECK( m_dvc->GetChildCount(wxDataViewItem()) == 0 );
}
TEST_CASE_METHOD(MultiColumnsDataViewCtrlTestCase,
"wxDVC::AppendTextColumn",
"[wxDataViewCtrl][column]")
{
#ifdef __WXGTK__
// Wait for the list control to be realized.
WaitFor("wxDataViewCtrl to be realized", [this]() {
return m_firstColumn->GetWidth() != 0;
});
#endif
// Check the width of the first column.
CHECK( m_firstColumn->GetWidth() == m_firstColumnWidth );
// Check that the last column was extended to fit client area.
const int lastColumnMaxWidth =
m_dvc->GetClientSize().GetWidth() - m_firstColumnWidth;
// In GTK and under Mac the width of the last column is less then
// a remaining client area.
const int lastColumnMinWidth = lastColumnMaxWidth - 10;
CHECK( m_lastColumn->GetWidth() <= lastColumnMaxWidth );
CHECK( m_lastColumn->GetWidth() >= lastColumnMinWidth );
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SingleSelectDataViewCtrlTestCase,
"wxDVC::KeyEvents",
"[wxDataViewCtrl][event]")
{
if ( !EnableUITests() )
return;
EventCounter keyEvents(m_dvc, wxEVT_KEY_DOWN);
m_dvc->SetFocus();
wxYield();
wxUIActionSimulator sim;
sim.Char(WXK_DOWN);
wxYield();
CHECK( keyEvents.GetCount() == 1 );
}
#endif // wxUSE_UIACTIONSIMULATOR
#endif //wxUSE_DATAVIEWCTRL

View File

@@ -0,0 +1,168 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/datepickerctrltest.cpp
// Purpose: wxDatePickerCtrl unit test
// Author: Vadim Zeitlin
// Created: 2011-06-18
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_DATEPICKCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/button.h"
#endif // WX_PRECOMP
#include "wx/datectrl.h"
#include "wx/uiaction.h"
#include "testableframe.h"
#include "testdate.h"
class DatePickerCtrlTestCase : public CppUnit::TestCase
{
public:
DatePickerCtrlTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( DatePickerCtrlTestCase );
CPPUNIT_TEST( Value );
CPPUNIT_TEST( Range );
WXUISIM_TEST( Focus );
CPPUNIT_TEST_SUITE_END();
void Value();
void Range();
void Focus();
wxDatePickerCtrl* m_datepicker;
wxButton* m_button;
wxDECLARE_NO_COPY_CLASS(DatePickerCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( DatePickerCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( DatePickerCtrlTestCase, "DatePickerCtrlTestCase" );
void DatePickerCtrlTestCase::setUp()
{
m_datepicker = new wxDatePickerCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
m_button = nullptr;
}
void DatePickerCtrlTestCase::tearDown()
{
delete m_button;
delete m_datepicker;
}
void DatePickerCtrlTestCase::Value()
{
const wxDateTime dt(18, wxDateTime::Jul, 2011);
m_datepicker->SetValue(dt);
CPPUNIT_ASSERT_EQUAL( dt, m_datepicker->GetValue() );
// We don't use wxDP_ALLOWNONE currently, hence a value is required.
WX_ASSERT_FAILS_WITH_ASSERT( m_datepicker->SetValue(wxDateTime()) );
}
void DatePickerCtrlTestCase::Range()
{
// Initially we have no valid range but MSW version still has (built in)
// minimum as it doesn't support dates before 1601-01-01, hence don't rely
// on GetRange() returning false.
wxDateTime dtRangeStart, dtRangeEnd;
// Default end date for QT is 31/12/7999 which is considered valid,
// therefore we should omit this assertion for QT
#ifndef __WXQT__
m_datepicker->GetRange(&dtRangeStart, &dtRangeEnd);
CPPUNIT_ASSERT( !dtRangeEnd.IsValid() );
#endif
// After we set it we should be able to get it back.
const wxDateTime
dtStart(15, wxDateTime::Feb, 1923),
dtEnd(18, wxDateTime::Jun, 2011);
m_datepicker->SetRange(dtStart, dtEnd);
CPPUNIT_ASSERT( m_datepicker->GetRange(&dtRangeStart, &dtRangeEnd) );
CPPUNIT_ASSERT_EQUAL( dtStart, dtRangeStart );
CPPUNIT_ASSERT_EQUAL( dtEnd, dtRangeEnd );
// Setting dates inside the range should work, including the range end
// points.
m_datepicker->SetValue(dtStart);
CPPUNIT_ASSERT_EQUAL( dtStart, m_datepicker->GetValue() );
m_datepicker->SetValue(dtEnd);
CPPUNIT_ASSERT_EQUAL( dtEnd, m_datepicker->GetValue() );
// Setting dates outside the range should not work.
m_datepicker->SetValue(dtEnd + wxTimeSpan::Day());
CPPUNIT_ASSERT_EQUAL( dtEnd, m_datepicker->GetValue() );
m_datepicker->SetValue(dtStart - wxTimeSpan::Day());
CPPUNIT_ASSERT_EQUAL( dtEnd, m_datepicker->GetValue() );
// Changing the range should clamp the current value to it if necessary.
const wxDateTime
dtBeforeEnd = dtEnd - wxDateSpan::Day();
m_datepicker->SetRange(dtStart, dtBeforeEnd);
CPPUNIT_ASSERT_EQUAL( dtBeforeEnd, m_datepicker->GetValue() );
}
#if wxUSE_UIACTIONSIMULATOR
static wxPoint GetRectCenter(const wxRect& r)
{
return (r.GetTopRight() + r.GetBottomLeft()) / 2;
}
void DatePickerCtrlTestCase::Focus()
{
// Create another control just to give focus to it initially.
m_button = new wxButton(wxTheApp->GetTopWindow(), wxID_OK);
m_button->Move(0, m_datepicker->GetSize().y * 3);
m_button->SetFocus();
wxYield();
CHECK( !m_datepicker->HasFocus() );
EventCounter setFocus(m_datepicker, wxEVT_SET_FOCUS);
EventCounter killFocus(m_datepicker, wxEVT_KILL_FOCUS);
wxUIActionSimulator sim;
sim.MouseMove(GetRectCenter(m_datepicker->GetScreenRect()));
sim.MouseClick();
wxYield();
REQUIRE( m_datepicker->HasFocus() );
CHECK( setFocus.GetCount() == 1 );
CHECK( killFocus.GetCount() == 0 );
sim.MouseMove(GetRectCenter(m_button->GetScreenRect()));
sim.MouseClick();
wxYield();
CHECK( !m_datepicker->HasFocus() );
CHECK( setFocus.GetCount() == 1 );
CHECK( killFocus.GetCount() == 1 );
}
#endif // wxUSE_UIACTIONSIMULATOR
#endif // wxUSE_DATEPICKCTRL

View File

@@ -0,0 +1,145 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/dialogtest.cpp
// Purpose: wxWindow unit test
// Author: Vaclav Slavik
// Created: 2012-08-30
// Copyright: (c) 2012 Vaclav Slavik
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#include "wx/testing.h"
#include "wx/msgdlg.h"
#include "wx/filedlg.h"
// This test suite tests helpers from wx/testing.h intended for testing of code
// that calls modal dialogs. It does not test the implementation of wxWidgets'
// dialogs.
TEST_CASE("Modal::MessageDialog", "[modal]")
{
int rc;
#if wxUSE_FILEDLG
#define FILE_DIALOG_TEST ,\
wxExpectModal<wxFileDialog>(wxGetCwd() + "/test.txt").Optional()
#else
#define FILE_DIALOG_TEST
#endif
wxTEST_DIALOG
(
rc = wxMessageBox("Should I fail?", "Question", wxYES|wxNO),
wxExpectModal<wxMessageDialog>(wxNO)
FILE_DIALOG_TEST
);
CHECK( rc == wxNO );
}
#if wxUSE_FILEDLG
TEST_CASE("Modal::FileDialog", "[modal]")
{
#if defined(__WXQT__) && defined(__WINDOWS__)
WARN("Skipping test known to fail under wxQt for Windows");
return;
#else
wxFileDialog dlg(nullptr);
int rc;
wxTEST_DIALOG
(
rc = dlg.ShowModal(),
wxExpectModal<wxFileDialog>(wxGetCwd() + "/test.txt")
);
CHECK( rc == wxID_OK );
CHECK( dlg.GetFilename() == "test.txt" );
#ifdef __WXGTK3__
// The native file dialog in GTK+ 3 launches an async operation which tries
// to dereference the already deleted dialog object if we don't let it to
// complete before leaving this function.
wxYield();
#endif
#endif
}
#endif
class MyDialog : public wxDialog
{
public:
MyDialog(wxWindow *parent) : wxDialog(parent, wxID_ANY, "Entry"), m_value(-1)
{
// Dummy. Imagine it's a real dialog that shows some number-entry
// controls.
}
int m_value;
};
template<>
class wxExpectModal<MyDialog> : public wxExpectModalBase<MyDialog>
{
public:
wxExpectModal(int valueToSet) : m_valueToSet(valueToSet) {}
protected:
virtual int OnInvoked(MyDialog *dlg) const override
{
// Simulate the user entering the expected number:
dlg->m_value = m_valueToSet;
return wxID_OK;
}
int m_valueToSet;
};
TEST_CASE("Modal::CustomDialog", "[modal]")
{
MyDialog dlg(nullptr);
wxTEST_DIALOG
(
dlg.ShowModal(),
wxExpectModal<MyDialog>(42)
);
CHECK( dlg.m_value == 42 );
}
class MyModalDialog : public wxDialog
{
public:
MyModalDialog() : wxDialog (nullptr, wxID_ANY, "Modal Dialog")
{
m_wasModal = false;
Bind( wxEVT_INIT_DIALOG, &MyModalDialog::OnInit, this );
}
void OnInit(wxInitDialogEvent& WXUNUSED(event))
{
m_wasModal = IsModal();
CallAfter( &MyModalDialog::EndModal, wxID_OK );
}
bool WasModal() const
{
return m_wasModal;
}
private:
bool m_wasModal;
};
TEST_CASE("Modal::InitDialog", "[modal]")
{
MyModalDialog dlg;
dlg.ShowModal();
CHECK( dlg.WasModal() );
}

View File

@@ -0,0 +1,77 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/frametest.cpp
// Purpose: wxFrame unit test
// Author: Steven Lamerton
// Created: 2010-07-10
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/frame.h"
#endif // WX_PRECOMP
#include "testableframe.h"
class FrameTestCase : public CppUnit::TestCase
{
public:
FrameTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( FrameTestCase );
CPPUNIT_TEST( Iconize );
CPPUNIT_TEST( Close );
CPPUNIT_TEST_SUITE_END();
void Iconize();
void Close();
wxFrame *m_frame;
wxDECLARE_NO_COPY_CLASS(FrameTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( FrameTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FrameTestCase, "FrameTestCase" );
void FrameTestCase::setUp()
{
m_frame = new wxFrame(nullptr, wxID_ANY, "test frame");
m_frame->Show();
}
void FrameTestCase::tearDown()
{
m_frame->Destroy();
}
void FrameTestCase::Iconize()
{
#ifdef __WXMSW__
EventCounter iconize(m_frame, wxEVT_ICONIZE);
m_frame->Iconize();
m_frame->Iconize(false);
CPPUNIT_ASSERT_EQUAL(2, iconize.GetCount());
#endif
}
void FrameTestCase::Close()
{
EventCounter close(m_frame, wxEVT_CLOSE_WINDOW);
m_frame->Close();
CPPUNIT_ASSERT_EQUAL(1, close.GetCount());
}

View File

@@ -0,0 +1,107 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/gaugetest.cpp
// Purpose: wxGauge unit test
// Author: Steven Lamerton
// Created: 2010-07-15
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_GAUGE
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/gauge.h"
#endif // WX_PRECOMP
class GaugeTestCase : public CppUnit::TestCase
{
public:
GaugeTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( GaugeTestCase );
CPPUNIT_TEST( Direction );
CPPUNIT_TEST( Range );
CPPUNIT_TEST( Value );
CPPUNIT_TEST_SUITE_END();
void Direction();
void Range();
void Value();
wxGauge* m_gauge;
wxDECLARE_NO_COPY_CLASS(GaugeTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( GaugeTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( GaugeTestCase, "GaugeTestCase" );
void GaugeTestCase::setUp()
{
m_gauge = new wxGauge(wxTheApp->GetTopWindow(), wxID_ANY, 100);
}
void GaugeTestCase::tearDown()
{
wxTheApp->GetTopWindow()->DestroyChildren();
}
void GaugeTestCase::Direction()
{
//We should default to a horizontal gauge
CPPUNIT_ASSERT(!m_gauge->IsVertical());
wxDELETE(m_gauge);
m_gauge = new wxGauge(wxTheApp->GetTopWindow(), wxID_ANY, 100,
wxDefaultPosition, wxDefaultSize, wxGA_VERTICAL);
CPPUNIT_ASSERT(m_gauge->IsVertical());
wxDELETE(m_gauge);
m_gauge = new wxGauge(wxTheApp->GetTopWindow(), wxID_ANY, 100,
wxDefaultPosition, wxDefaultSize, wxGA_HORIZONTAL);
CPPUNIT_ASSERT(!m_gauge->IsVertical());
}
void GaugeTestCase::Range()
{
CPPUNIT_ASSERT_EQUAL(100, m_gauge->GetRange());
m_gauge->SetRange(50);
CPPUNIT_ASSERT_EQUAL(50, m_gauge->GetRange());
m_gauge->SetRange(0);
CPPUNIT_ASSERT_EQUAL(0, m_gauge->GetRange());
}
void GaugeTestCase::Value()
{
CPPUNIT_ASSERT_EQUAL(0, m_gauge->GetValue());
m_gauge->SetValue(50);
CPPUNIT_ASSERT_EQUAL(50, m_gauge->GetValue());
m_gauge->SetValue(0);
CPPUNIT_ASSERT_EQUAL(0, m_gauge->GetValue());
m_gauge->SetValue(100);
CPPUNIT_ASSERT_EQUAL(100, m_gauge->GetValue());
}
#endif //wxUSE_GAUGE

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,145 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/headerctrltest.cpp
// Purpose: wxHeaderCtrl unit test
// Author: Vadim Zeitlin
// Created: 2008-11-26
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/headerctrl.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class HeaderCtrlTestCase : public CppUnit::TestCase
{
public:
HeaderCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
CPPUNIT_TEST_SUITE( HeaderCtrlTestCase );
CPPUNIT_TEST( AddDelete );
CPPUNIT_TEST( BestSize );
CPPUNIT_TEST( Reorder );
CPPUNIT_TEST_SUITE_END();
void AddDelete();
void BestSize();
void Reorder();
wxHeaderCtrlSimple *m_header;
wxDECLARE_NO_COPY_CLASS(HeaderCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( HeaderCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( HeaderCtrlTestCase, "HeaderCtrlTestCase" );
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void HeaderCtrlTestCase::setUp()
{
m_header = new wxHeaderCtrlSimple(wxTheApp->GetTopWindow());
}
void HeaderCtrlTestCase::tearDown()
{
delete m_header;
m_header = nullptr;
}
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
void HeaderCtrlTestCase::AddDelete()
{
CPPUNIT_ASSERT_EQUAL( 0, m_header->GetColumnCount() );
m_header->AppendColumn(wxHeaderColumnSimple("Column 1"));
CPPUNIT_ASSERT_EQUAL( 1, m_header->GetColumnCount() );
m_header->AppendColumn(wxHeaderColumnSimple("Column 2"));
CPPUNIT_ASSERT_EQUAL( 2, m_header->GetColumnCount() );
m_header->InsertColumn(wxHeaderColumnSimple("Column 0"), 0);
CPPUNIT_ASSERT_EQUAL( 3, m_header->GetColumnCount() );
m_header->DeleteColumn(2);
CPPUNIT_ASSERT_EQUAL( 2, m_header->GetColumnCount() );
}
void HeaderCtrlTestCase::BestSize()
{
const wxSize sizeEmpty = m_header->GetBestSize();
// this fails under wxGTK where wxControl::GetBestSize() is 0 in horizontal
// direction
//CPPUNIT_ASSERT( sizeEmpty.x > 0 );
CPPUNIT_ASSERT( sizeEmpty.y > 0 );
m_header->AppendColumn(wxHeaderColumnSimple("Foo"));
m_header->AppendColumn(wxHeaderColumnSimple("Bar"));
const wxSize size = m_header->GetBestSize();
CPPUNIT_ASSERT_EQUAL( sizeEmpty.y, size.y );
}
void HeaderCtrlTestCase::Reorder()
{
static const int COL_COUNT = 4;
int n;
for ( n = 0; n < COL_COUNT; n++ )
m_header->AppendColumn(wxHeaderColumnSimple(wxString::Format("%d", n)));
wxArrayInt order = m_header->GetColumnsOrder(); // initial order: [0 1 2 3]
for ( n = 0; n < COL_COUNT; n++ )
CPPUNIT_ASSERT_EQUAL( n, order[n] );
wxHeaderCtrl::MoveColumnInOrderArray(order, 0, 2);
m_header->SetColumnsOrder(order); // change order to [1 2 0 3]
order = m_header->GetColumnsOrder();
CPPUNIT_ASSERT_EQUAL( 1, order[0] );
CPPUNIT_ASSERT_EQUAL( 2, order[1] );
CPPUNIT_ASSERT_EQUAL( 0, order[2] );
CPPUNIT_ASSERT_EQUAL( 3, order[3] );
order[2] = 3;
order[3] = 0;
m_header->SetColumnsOrder(order); // and now [1 2 3 0]
order = m_header->GetColumnsOrder();
CPPUNIT_ASSERT_EQUAL( 1, order[0] );
CPPUNIT_ASSERT_EQUAL( 2, order[1] );
CPPUNIT_ASSERT_EQUAL( 3, order[2] );
CPPUNIT_ASSERT_EQUAL( 0, order[3] );
wxHeaderCtrl::MoveColumnInOrderArray(order, 1, 3);
m_header->SetColumnsOrder(order); // finally [2 3 0 1]
order = m_header->GetColumnsOrder();
CPPUNIT_ASSERT_EQUAL( 2, order[0] );
CPPUNIT_ASSERT_EQUAL( 3, order[1] );
CPPUNIT_ASSERT_EQUAL( 0, order[2] );
CPPUNIT_ASSERT_EQUAL( 1, order[3] );
}

View File

@@ -0,0 +1,56 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/htmllboxtest.cpp
// Purpose: wxSimpleHtmlListBoxNameStr unit test
// Author: Vadim Zeitlin
// Created: 2010-11-27
// Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_HTML
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/htmllbox.h"
#include "itemcontainertest.h"
class HtmlListBoxTestCase : public ItemContainerTestCase,
public CppUnit::TestCase
{
public:
HtmlListBoxTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxItemContainer *GetContainer() const override { return m_htmllbox; }
virtual wxWindow *GetContainerWindow() const override { return m_htmllbox; }
CPPUNIT_TEST_SUITE( HtmlListBoxTestCase );
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST_SUITE_END();
wxSimpleHtmlListBox* m_htmllbox;
wxDECLARE_NO_COPY_CLASS(HtmlListBoxTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(HtmlListBoxTestCase,
"[HtmlListBoxTestCase][item-container]");
void HtmlListBoxTestCase::setUp()
{
m_htmllbox = new wxSimpleHtmlListBox(wxTheApp->GetTopWindow(), wxID_ANY);
}
void HtmlListBoxTestCase::tearDown()
{
wxDELETE(m_htmllbox);
}
#endif //wxUSE_HTML

View File

@@ -0,0 +1,103 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/hyperlinkctrltest.cpp
// Purpose: wxHyperlinkCtrl unit test
// Author: Steven Lamerton
// Created: 2010-08-05
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_HYPERLINKCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/hyperlink.h"
#include "wx/uiaction.h"
#include "testableframe.h"
#include "asserthelper.h"
class HyperlinkCtrlTestCase
{
public:
HyperlinkCtrlTestCase()
{
m_hyperlink = new wxHyperlinkCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
"wxWidgets", "http://wxwidgets.org");
}
~HyperlinkCtrlTestCase()
{
delete m_hyperlink;
}
protected:
wxHyperlinkCtrl* m_hyperlink;
wxDECLARE_NO_COPY_CLASS(HyperlinkCtrlTestCase);
};
TEST_CASE_METHOD(HyperlinkCtrlTestCase, "wxHyperlinkCtrl::Colour",
"[hyperlinkctrl]")
{
#ifndef __WXGTK__
CHECK(m_hyperlink->GetHoverColour().IsOk());
CHECK(m_hyperlink->GetNormalColour().IsOk());
CHECK(m_hyperlink->GetVisitedColour().IsOk());
// Changing hover colour doesn't work in wxMSW and Wine doesn't seem to
// implement either LM_SETITEM or LM_GETITEM correctly, so skip this there.
#ifdef __WXMSW__
if ( wxIsRunningUnderWine() )
{
WARN("Skipping testing wxHyperlinkCtrl colours under Wine.");
return;
}
#else // __WXMSW__
m_hyperlink->SetHoverColour(*wxGREEN);
CHECK( m_hyperlink->GetHoverColour() == *wxGREEN );
#endif // __WXMSW__/!__WXMSW__
m_hyperlink->SetNormalColour(*wxRED);
CHECK( m_hyperlink->GetNormalColour() == *wxRED );
m_hyperlink->SetVisitedColour(*wxBLUE);
CHECK( m_hyperlink->GetVisitedColour() == *wxBLUE );
#endif
}
TEST_CASE_METHOD(HyperlinkCtrlTestCase, "wxHyperlinkCtrl::Url",
"[hyperlinkctrl]")
{
CHECK( m_hyperlink->GetURL() == "http://wxwidgets.org" );
m_hyperlink->SetURL("http://google.com");
CHECK( m_hyperlink->GetURL() == "http://google.com" );
}
TEST_CASE_METHOD(HyperlinkCtrlTestCase, "wxHyperlinkCtrl::Click",
"[hyperlinkctrl]")
{
#if wxUSE_UIACTIONSIMULATOR
if ( !EnableUITests() )
return;
EventCounter hyperlink(m_hyperlink, wxEVT_HYPERLINK);
wxUIActionSimulator sim;
sim.MouseMove(m_hyperlink->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick();
wxYield();
CHECK( hyperlink.GetCount() == 1 );
#endif
}
#endif //wxUSE_HYPERLINKCTRL

View File

@@ -0,0 +1,43 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/infobar.cpp
// Purpose: wxInfoBar tests
// Author: Blake Madden
// Created: 2025-6-02
// Copyright: (c) 2025 Blake Madden
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_INFOBAR
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/infobar.h"
#include <memory>
TEST_CASE("wxInfoBar::Buttons", "[wxInfoBar]")
{
const std::unique_ptr<wxInfoBar>
info(new wxInfoBar(wxTheApp->GetTopWindow(), wxID_ANY, wxINFOBAR_CHECKBOX));
CHECK(info->GetButtonCount() == 0);
const int buttonId = wxID_HIGHEST + 1000;
info->AddButton(buttonId, "test");
CHECK(info->GetButtonCount() == 1);
CHECK(info->GetButtonId(0) == buttonId);
CHECK(info->HasButtonId(buttonId));
info->RemoveButton(buttonId);
CHECK(info->GetButtonCount() == 0);
}
#endif // wxUSE_INFOBAR

View File

@@ -0,0 +1,360 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/itemcontainertest.cpp
// Purpose: wxItemContainer unit test
// Author: Steven Lamerton
// Created: 2010-06-29
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/ctrlsub.h"
#endif // WX_PRECOMP
#include "wx/scopeguard.h"
#include "wx/uiaction.h"
#include "itemcontainertest.h"
void ItemContainerTestCase::Append()
{
wxItemContainer * const container = GetContainer();
container->Append("item 0");
CPPUNIT_ASSERT_EQUAL("item 0", container->GetString(0));
wxArrayString testitems;
testitems.Add("item 1");
testitems.Add("item 2");
container->Append(testitems);
CPPUNIT_ASSERT_EQUAL("item 1", container->GetString(1));
CPPUNIT_ASSERT_EQUAL("item 2", container->GetString(2));
wxString arritems[] = { "item 3", "item 4" };
container->Append(2, arritems);
CPPUNIT_ASSERT_EQUAL("item 3", container->GetString(3));
CPPUNIT_ASSERT_EQUAL("item 4", container->GetString(4));
}
void ItemContainerTestCase::Insert()
{
wxItemContainer * const container = GetContainer();
CPPUNIT_ASSERT_EQUAL( 0, container->Insert("item 0", 0) );
CPPUNIT_ASSERT_EQUAL("item 0", container->GetString(0));
wxArrayString testitems;
testitems.Add("item 1");
testitems.Add("item 2");
CPPUNIT_ASSERT_EQUAL( 1, container->Insert(testitems, 0) );
CPPUNIT_ASSERT_EQUAL("item 1", container->GetString(0));
CPPUNIT_ASSERT_EQUAL("item 2", container->GetString(1));
wxString arritems[] = { "item 3", "item 4" };
CPPUNIT_ASSERT_EQUAL( 2, container->Insert(2, arritems, 1) );
CPPUNIT_ASSERT_EQUAL("item 3", container->GetString(1));
CPPUNIT_ASSERT_EQUAL("item 4", container->GetString(2));
}
void ItemContainerTestCase::Count()
{
wxItemContainer * const container = GetContainer();
CPPUNIT_ASSERT(container->IsEmpty());
WX_ASSERT_FAILS_WITH_ASSERT( container->GetString(0) );
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
testitems.Add("item 3");
container->Append(testitems);
CPPUNIT_ASSERT(!container->IsEmpty());
CPPUNIT_ASSERT_EQUAL(4, container->GetCount());
container->Delete(0);
CPPUNIT_ASSERT_EQUAL(3, container->GetCount());
container->Delete(0);
container->Delete(0);
CPPUNIT_ASSERT_EQUAL(1, container->GetCount());
container->Insert(testitems, 1);
CPPUNIT_ASSERT_EQUAL(5, container->GetCount());
WX_ASSERT_FAILS_WITH_ASSERT( container->GetString(10) );
}
void ItemContainerTestCase::ItemSelection()
{
wxItemContainer * const container = GetContainer();
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
testitems.Add("ITEM 2"); // The same as the last one except for case.
container->Append(testitems);
container->SetSelection(wxNOT_FOUND);
CPPUNIT_ASSERT_EQUAL(wxNOT_FOUND, container->GetSelection());
CPPUNIT_ASSERT_EQUAL("", container->GetStringSelection());
container->SetSelection(1);
CPPUNIT_ASSERT_EQUAL(1, container->GetSelection());
CPPUNIT_ASSERT_EQUAL("item 1", container->GetStringSelection());
CPPUNIT_ASSERT( container->SetStringSelection("item 2") );
CPPUNIT_ASSERT_EQUAL(2, container->GetSelection());
CPPUNIT_ASSERT_EQUAL("item 2", container->GetStringSelection());
// Check that selecting a non-existent item fails.
CPPUNIT_ASSERT( !container->SetStringSelection("bloordyblop") );
// Check that SetStringSelection() is case-insensitive.
CPPUNIT_ASSERT( container->SetStringSelection("ITEM 2") );
CPPUNIT_ASSERT_EQUAL(2, container->GetSelection());
CPPUNIT_ASSERT_EQUAL("item 2", container->GetStringSelection());
}
void ItemContainerTestCase::FindString()
{
wxItemContainer * const container = GetContainer();
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
testitems.Add("item 3");
container->Append(testitems);
CPPUNIT_ASSERT_EQUAL(1, container->FindString("item 1"));
CPPUNIT_ASSERT_EQUAL(1, container->FindString("ITEM 1"));
CPPUNIT_ASSERT_EQUAL(wxNOT_FOUND, container->FindString("ITEM 1", true));
}
void ItemContainerTestCase::ClientData()
{
wxItemContainer * const container = GetContainer();
wxStringClientData* item0data = new wxStringClientData("item0data");
wxStringClientData* item1data = new wxStringClientData("item1data");
wxStringClientData* item2data = new wxStringClientData("item2data");
container->Append("item 0", item0data);
CPPUNIT_ASSERT_EQUAL(static_cast<wxClientData*>(item0data),
container->GetClientObject(0));
container->Append("item 1");
container->SetClientObject(1, item1data);
CPPUNIT_ASSERT_EQUAL(static_cast<wxClientData*>(item1data),
container->GetClientObject(1));
container->Insert("item 2", 2, item2data);
CPPUNIT_ASSERT_EQUAL(static_cast<wxClientData*>(item2data),
container->GetClientObject(2));
WX_ASSERT_FAILS_WITH_ASSERT( container->SetClientObject((unsigned)-1, item0data) );
WX_ASSERT_FAILS_WITH_ASSERT( container->SetClientObject(12345, item0data) );
}
void ItemContainerTestCase::VoidData()
{
wxItemContainer * const container = GetContainer();
wxString item0data("item0data"), item1data("item0data"),
item2data("item0data");
void* item0 = &item0data;
void* item1 = &item1data;
void* item2 = &item2data;
container->Append("item 0", item0);
CPPUNIT_ASSERT_EQUAL(item0, container->GetClientData(0));
container->Append("item 1");
container->SetClientData(1, item1);
CPPUNIT_ASSERT_EQUAL(item1, container->GetClientData(1));
container->Insert("item 2", 2, item2);
CPPUNIT_ASSERT_EQUAL(item2, container->GetClientData(2));
WX_ASSERT_FAILS_WITH_ASSERT( container->SetClientData((unsigned)-1, nullptr) );
WX_ASSERT_FAILS_WITH_ASSERT( container->SetClientData(12345, nullptr) );
// wxMSW used to hace problems retrieving the client data of -1 from a few
// standard controls, especially if the last error was set before doing it,
// so test for this specially.
const wxUIntPtr minus1 = static_cast<wxUIntPtr>(-1);
container->Append("item -1", wxUIntToPtr(minus1));
#ifdef __WINDOWS__
::SetLastError(ERROR_INVALID_DATA);
#endif
CPPUNIT_ASSERT_EQUAL( minus1, wxPtrToUInt(container->GetClientData(3)) );
}
void ItemContainerTestCase::Set()
{
wxItemContainer * const container = GetContainer();
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
container->Append(testitems);
wxArrayString newtestitems;
newtestitems.Add("new item 0");
newtestitems.Add("new item 1");
newtestitems.Add("new item 2");
newtestitems.Add("new item 3");
container->Set(newtestitems);
CPPUNIT_ASSERT_EQUAL(4, container->GetCount());
CPPUNIT_ASSERT_EQUAL("new item 1", container->GetString(1));
wxString arrnewitems[] = { "even newer 0", "event newer 1" };
container->Set(2, arrnewitems);
CPPUNIT_ASSERT_EQUAL(2, container->GetCount());
CPPUNIT_ASSERT_EQUAL("even newer 0", container->GetString(0));
}
void ItemContainerTestCase::SetString()
{
wxItemContainer * const container = GetContainer();
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
testitems.Add("item 3");
container->Append(testitems);
container->SetSelection(0);
container->SetString(0, "new item 0");
CPPUNIT_ASSERT_EQUAL("new item 0", container->GetString(0));
// Modifying the item shouldn't deselect it.
CPPUNIT_ASSERT_EQUAL(0, container->GetSelection());
// wxOSX doesn't support having empty items in some containers.
#ifndef __WXOSX__
container->SetString(2, "");
CPPUNIT_ASSERT_EQUAL("", container->GetString(2));
#endif
}
void ItemContainerTestCase::SelectionAfterDelete()
{
wxItemContainer * const container = GetContainer();
container->Append("item 0");
container->Append("item 1");
container->Append("item 2");
container->Append("item 3");
container->SetSelection(1);
CHECK( container->GetSelection() == 1 );
container->Delete(3);
CHECK( container->GetSelection() == 1 );
container->Delete(1);
CHECK( container->GetSelection() == wxNOT_FOUND );
container->SetSelection(1);
container->Delete(1);
CHECK( container->GetSelection() == wxNOT_FOUND );
container->SetSelection(0);
container->Delete(0);
CHECK( container->GetSelection() == wxNOT_FOUND );
}
void ItemContainerTestCase::SetSelection()
{
wxItemContainer * const container = GetContainer();
container->Append("first");
container->Append("second");
// This class is used to check that SetSelection() doesn't generate any
// events, as documented.
class CommandEventHandler : public wxEvtHandler
{
public:
virtual bool ProcessEvent(wxEvent& event) override
{
CPPUNIT_ASSERT_MESSAGE
(
"unexpected command event from SetSelection",
!event.IsCommandEvent()
);
return wxEvtHandler::ProcessEvent(event);
}
} h;
wxWindow * const win = GetContainerWindow();
win->PushEventHandler(&h);
wxON_BLOCK_EXIT_OBJ1( *win, wxWindow::PopEventHandler, false );
container->SetSelection(0);
CPPUNIT_ASSERT_EQUAL( 0, container->GetSelection() );
container->SetSelection(1);
CPPUNIT_ASSERT_EQUAL( 1, container->GetSelection() );
}
#if wxUSE_UIACTIONSIMULATOR
void ItemContainerTestCase::SimSelect()
{
wxItemContainer * const container = GetContainer();
container->Append("first");
container->Append("second");
container->Append("third");
GetContainerWindow()->SetFocus();
wxYield();
wxUIActionSimulator sim;
CPPUNIT_ASSERT( sim.Select("third") );
CPPUNIT_ASSERT_EQUAL( 2, container->GetSelection() );
CPPUNIT_ASSERT( sim.Select("first") );
CPPUNIT_ASSERT_EQUAL( 0, container->GetSelection() );
CPPUNIT_ASSERT( !sim.Select("tenth") );
}
#endif // wxUSE_UIACTIONSIMULATOR

View File

@@ -0,0 +1,65 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/itemcontainertest.h
// Purpose: wxItemContainer unit test
// Author: Steven Lamerton
// Created: 2010-06-29
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_TESTS_CONTROLS_ITEMCONTAINERTEST_H_
#define _WX_TESTS_CONTROLS_ITEMCONTAINERTEST_H_
class ItemContainerTestCase
{
public:
ItemContainerTestCase() { }
virtual ~ItemContainerTestCase() { }
protected:
// this function must be overridden by the derived classes to return the
// text entry object we're testing, typically this is done by creating a
// control implementing wxItemContainer interface in setUp() virtual method and
// just returning it from here
virtual wxItemContainer *GetContainer() const = 0;
// and this one must be overridden to return the window which implements
// wxItemContainer interface -- usually it will return the same pointer as
// GetContainer(), just as a different type
virtual wxWindow *GetContainerWindow() const = 0;
// this should be inserted in the derived class CPPUNIT_TEST_SUITE
// definition to run all wxItemContainer tests as part of it
#define wxITEM_CONTAINER_TESTS() \
CPPUNIT_TEST( Append ); \
CPPUNIT_TEST( Insert ); \
CPPUNIT_TEST( Count ); \
CPPUNIT_TEST( ItemSelection ); \
CPPUNIT_TEST( FindString ); \
CPPUNIT_TEST( ClientData ); \
CPPUNIT_TEST( VoidData ); \
CPPUNIT_TEST( Set ); \
CPPUNIT_TEST( SetSelection ); \
CPPUNIT_TEST( SetString ); \
CPPUNIT_TEST( SelectionAfterDelete ); \
WXUISIM_TEST( SimSelect );
void Append();
void Insert();
void Count();
void ItemSelection();
void FindString();
void ClientData();
void VoidData();
void Set();
void SetSelection();
void SetString();
void SelectionAfterDelete();
#if wxUSE_UIACTIONSIMULATOR
virtual void SimSelect();
#endif
private:
wxDECLARE_NO_COPY_CLASS(ItemContainerTestCase);
};
#endif // _WX_TESTS_CONTROLS_ITEMCONTAINERTEST_H_

View File

@@ -0,0 +1,149 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/label.cpp
// Purpose: wxControl and wxStaticText label tests
// Author: Francesco Montorsi
// Created: 2010-3-21
// Copyright: (c) 2010 Francesco Montorsi
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/checkbox.h"
#include "wx/control.h"
#include "wx/stattext.h"
#include "wx/textctrl.h"
#include "wx/generic/stattextg.h"
#include <memory>
namespace
{
const char* const ORIGINAL_LABEL = "origin label";
// The actual testing function. It will change the label of the provided
// control, which is assumed to be ORIGINAL_LABEL initially.
void DoTestLabel(wxControl* c)
{
CHECK( c->GetLabel() == ORIGINAL_LABEL );
const wxString testLabelArray[] = {
"label without mnemonics and markup",
"label with &mnemonic",
"label with <span foreground='blue'>some</span> <b>markup</b>",
"label with <span foreground='blue'>some</span> <b>markup</b> and &mnemonic",
"label with an && (ampersand)",
"label with an && (&ampersand)",
"", // empty label should work too
};
for ( unsigned int s = 0; s < WXSIZEOF(testLabelArray); s++ )
{
const wxString& l = testLabelArray[s];
// GetLabel() should always return the string passed to SetLabel()
c->SetLabel(l);
CHECK( c->GetLabel() == l );
// GetLabelText() should always return unescaped version of the label
CHECK( c->GetLabelText() == wxControl::RemoveMnemonics(l) );
// GetLabelText() should always return the string passed to SetLabelText()
c->SetLabelText(l);
CHECK( c->GetLabelText() == l );
// And GetLabel() should be the escaped version of the text
CHECK( l == wxControl::RemoveMnemonics(c->GetLabel()) );
}
// Check that both "&" and "&amp;" work in markup.
#if wxUSE_MARKUP
c->SetLabelMarkup("mnemonic in &amp;markup");
CHECK( c->GetLabel() == "mnemonic in &markup" );
CHECK( c->GetLabelText() == "mnemonic in markup" );
c->SetLabelMarkup("mnemonic in &markup");
CHECK( c->GetLabel() == "mnemonic in &markup" );
CHECK( c->GetLabelText() == "mnemonic in markup" );
c->SetLabelMarkup("&amp;&amp; finally");
CHECK( c->GetLabel() == "&& finally" );
CHECK( c->GetLabelText() == "& finally" );
c->SetLabelMarkup("&& finally");
CHECK( c->GetLabel() == "&& finally" );
CHECK( c->GetLabelText() == "& finally" );
#endif // wxUSE_MARKUP
}
} // anonymous namespace
TEST_CASE("wxControl::Label", "[wxControl][label]")
{
SECTION("wxStaticText")
{
const std::unique_ptr<wxStaticText>
st(new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL));
DoTestLabel(st.get());
}
SECTION("wxStaticText/ellipsized")
{
const std::unique_ptr<wxStaticText>
st(new wxStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL,
wxDefaultPosition, wxDefaultSize,
wxST_ELLIPSIZE_START));
DoTestLabel(st.get());
}
SECTION("wxGenericStaticText")
{
const std::unique_ptr<wxGenericStaticText>
gst(new wxGenericStaticText(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL));
DoTestLabel(gst.get());
}
SECTION("wxCheckBox")
{
const std::unique_ptr<wxCheckBox>
cb(new wxCheckBox(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL));
DoTestLabel(cb.get());
}
SECTION("wxTextCtrl")
{
const std::unique_ptr<wxTextCtrl>
tc(new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, ORIGINAL_LABEL));
// Setting the label of a wxTextCtrl should _not_ work, it has value
// and not a label.
WX_ASSERT_FAILS_WITH_ASSERT( tc->SetLabel("something else") );
CHECK( tc->GetValue() == ORIGINAL_LABEL );
}
}
TEST_CASE("wxControl::RemoveMnemonics", "[wxControl][label][mnemonics]")
{
CHECK( "mnemonic" == wxControl::RemoveMnemonics("&mnemonic") );
CHECK( "&mnemonic" == wxControl::RemoveMnemonics("&&mnemonic") );
CHECK( "&mnemonic" == wxControl::RemoveMnemonics("&&&mnemonic") );
}
TEST_CASE("wxControl::FindAccelIndex", "[wxControl][label][mnemonics]")
{
CHECK( wxControl::FindAccelIndex("foo") == wxNOT_FOUND );
CHECK( wxControl::FindAccelIndex("&foo") == 0 );
CHECK( wxControl::FindAccelIndex("f&oo") == 1 );
CHECK( wxControl::FindAccelIndex("foo && bar") == wxNOT_FOUND );
CHECK( wxControl::FindAccelIndex("foo && &bar") == 6 );
}

View File

@@ -0,0 +1,671 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/listbasetest.cpp
// Purpose: Common wxListCtrl and wxListView tests
// Author: Steven Lamerton
// Created: 2010-07-20
// Copyright: (c) 2008,2025 Vadim Zeitlin <vadim@wxwidgets.org>,
// (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_LISTCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/listctrl.h"
#include "listbasetest.h"
#include "testableframe.h"
#include "asserthelper.h"
#include "wx/uiaction.h"
#include "wx/imaglist.h"
#include "wx/artprov.h"
#include "wx/stopwatch.h"
void ListBaseTestCase::ColumnsOrder()
{
#ifdef wxHAS_LISTCTRL_COLUMN_ORDER
wxListCtrl* const list = GetList();
int n;
wxListItem li;
li.SetMask(wxLIST_MASK_TEXT);
// first set up some columns
static const int NUM_COLS = 3;
list->InsertColumn(0, "Column 0");
list->InsertColumn(1, "Column 1");
list->InsertColumn(2, "Column 2");
// and a couple of test items too
list->InsertItem(0, "Item 0");
list->SetItem(0, 1, "first in first");
list->InsertItem(1, "Item 1");
list->SetItem(1, 2, "second in second");
// check that the order is natural in the beginning
const wxArrayInt orderOrig = list->GetColumnsOrder();
for ( n = 0; n < NUM_COLS; n++ )
CHECK( orderOrig[n] == n );
// then rearrange them: using { 2, 0, 1 } order means that column 2 is
// shown first, then column 0 and finally column 1
wxArrayInt order(3);
order[0] = 2;
order[1] = 0;
order[2] = 1;
list->SetColumnsOrder(order);
// check that we get back the same order as we set
const wxArrayInt orderNew = list->GetColumnsOrder();
for ( n = 0; n < NUM_COLS; n++ )
CHECK( orderNew[n] == order[n] );
// and the order -> index mappings for individual columns
for ( n = 0; n < NUM_COLS; n++ )
CHECK( list->GetColumnIndexFromOrder(n) == order[n] );
// and also the reverse mapping
CHECK( list->GetColumnOrder(0) == 1 );
CHECK( list->GetColumnOrder(1) == 2 );
CHECK( list->GetColumnOrder(2) == 0 );
// finally check that accessors still use indices, not order
CHECK( list->GetColumn(0, li) );
CHECK( li.GetText() == "Column 0" );
li.SetId(0);
li.SetColumn(1);
CHECK( list->GetItem(li) );
CHECK( li.GetText() == "first in first" );
li.SetId(1);
li.SetColumn(2);
CHECK( list->GetItem(li) );
CHECK( li.GetText() == "second in second" );
#endif // wxHAS_LISTCTRL_COLUMN_ORDER
}
void ListBaseTestCase::ItemRect()
{
wxListCtrl* const list = GetList();
// set up for the test
list->InsertColumn(0, "Column 0", wxLIST_FORMAT_LEFT, 60);
list->InsertColumn(1, "Column 1", wxLIST_FORMAT_LEFT, 50);
list->InsertColumn(2, "Column 2", wxLIST_FORMAT_LEFT, 40);
list->InsertItem(0, "Item 0");
list->SetItem(0, 1, "first column");
list->SetItem(0, 1, "second column");
// do test
wxRect r;
WX_ASSERT_FAILS_WITH_ASSERT( list->GetItemRect(1, r) );
CHECK( list->GetItemRect(0, r) );
CHECK( r.GetWidth() == 150 );
CHECK( list->GetSubItemRect(0, 0, r) );
CHECK( r.GetWidth() == 60 );
CHECK( list->GetSubItemRect(0, 1, r) );
CHECK( r.GetWidth() == 50 );
CHECK( list->GetSubItemRect(0, 2, r) );
CHECK( r.GetWidth() == 40 );
WX_ASSERT_FAILS_WITH_ASSERT( list->GetSubItemRect(0, 3, r) );
// As we have a header, the top item shouldn't be at (0, 0), but somewhere
// below the header.
//
// Notice that we consider that the header can't be less than 10 pixels
// because we don't know its exact height.
CHECK( list->GetItemRect(0, r) );
CHECK( r.y >= 10 );
// However if we remove the header now, the item should be at (0, 0).
list->SetWindowStyle(wxLC_REPORT | wxLC_NO_HEADER);
CHECK( list->GetItemRect(0, r) );
CHECK( r.y == 0 );
}
void ListBaseTestCase::ItemText()
{
wxListCtrl* const list = GetList();
list->InsertColumn(0, "First");
list->InsertColumn(1, "Second");
list->InsertItem(0, "0,0");
CHECK( list->GetItemText(0) == "0,0" );
CHECK( list->GetItemText(0, 1) == "" );
list->SetItem(0, 1, "0,1");
CHECK( list->GetItemText(0, 1) == "0,1" );
}
void ListBaseTestCase::ChangeMode()
{
wxListCtrl* const list = GetList();
list->InsertColumn(0, "Header");
list->InsertItem(0, "First");
list->InsertItem(1, "Second");
CHECK( list->GetItemCount() == 2 );
// check that switching the mode preserves the items
list->SetWindowStyle(wxLC_ICON);
CHECK( list->GetItemCount() == 2 );
CHECK( list->GetItemText(0) == "First" );
// and so does switching back
list->SetWindowStyle(wxLC_REPORT);
CHECK( list->GetItemCount() == 2 );
CHECK( list->GetItemText(0) == "First" );
}
void ListBaseTestCase::MultiSelect()
{
#if wxUSE_UIACTIONSIMULATOR
if ( !EnableUITests() )
return;
#if defined(__WXGTK__) && !defined(__WXGTK3__)
// FIXME: This test fails on GitHub CI under wxGTK2 although works fine on
// development machine, no idea why though!
if ( IsAutomaticTest() )
return;
#endif // wxGTK2
wxListCtrl* const list = GetList();
EventCounter focused(list, wxEVT_LIST_ITEM_FOCUSED);
EventCounter selected(list, wxEVT_LIST_ITEM_SELECTED);
EventCounter deselected(list, wxEVT_LIST_ITEM_DESELECTED);
list->InsertColumn(0, "Header");
for ( int i = 0; i < 10; ++i )
list->InsertItem(i, wxString::Format("Item %d", i));
wxUIActionSimulator sim;
wxRect pos;
list->GetItemRect(2, pos); // Choose the third item as anchor
// We move in slightly so we are not on the edge
wxPoint point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
sim.MouseMove(point);
wxYield();
sim.MouseClick(); // select the anchor
wxYield();
list->GetItemRect(5, pos);
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
sim.MouseMove(point);
wxYield();
sim.KeyDown(WXK_SHIFT);
sim.MouseClick();
sim.KeyUp(WXK_SHIFT);
wxYield();
// when the first item was selected the focus changes to it, but not
// on subsequent clicks
CHECK( list->GetSelectedItemCount() == 4 ); // item 2 to 5 (inclusive) are selected
CHECK( focused.GetCount() == 2 ); // count the focus which was on the anchor
CHECK( selected.GetCount() == 4 );
CHECK( deselected.GetCount() == 0 );
focused.Clear();
selected.Clear();
deselected.Clear();
sim.Char(WXK_END, wxMOD_SHIFT); // extend the selection to the last item
wxYield();
CHECK( list->GetSelectedItemCount() == 8 ); // item 2 to 9 (inclusive) are selected
CHECK( focused.GetCount() == 1 ); // focus is on the last item
CHECK( selected.GetCount() == 4); // only newly selected items got the event
CHECK( deselected.GetCount() == 0 );
focused.Clear();
selected.Clear();
deselected.Clear();
sim.Char(WXK_HOME, wxMOD_SHIFT); // select from anchor to the first item
wxYield();
CHECK( list->GetSelectedItemCount() == 3 ); // item 0 to 2 (inclusive) are selected
CHECK( focused.GetCount() == 1 ); // focus is on item 0
CHECK( selected.GetCount() == 2 ); // events are only generated for item 0 and 1
CHECK( deselected.GetCount() == 7 ); // item 2 (exclusive) to 9 are deselected
focused.Clear();
selected.Clear();
deselected.Clear();
list->EnsureVisible(0);
wxYield();
list->GetItemRect(2, pos);
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
sim.MouseMove(point);
wxYield();
sim.MouseClick();
wxYield();
CHECK( list->GetSelectedItemCount() == 1 ); // anchor is the only selected item
CHECK( focused.GetCount() == 1 ); // because the focus changed from item 0 to anchor
CHECK( selected.GetCount() == 0 ); // anchor is already in selection state
CHECK( deselected.GetCount() == 2 ); // items 0 and 1 are deselected
focused.Clear();
selected.Clear();
deselected.Clear();
list->GetItemRect(3, pos);
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
// select and deselect item 3 while leaving item 2 selected
for ( int i = 0; i < 2; ++i )
{
sim.MouseMove(point + wxPoint(i*10, 0));
wxYield();
sim.KeyDown(WXK_CONTROL);
sim.MouseClick();
sim.KeyUp(WXK_CONTROL);
wxYield();
}
// select only item 3
sim.MouseMove(point);
wxYield();
sim.MouseClick();
wxYield();
CHECK( list->GetSelectedItemCount() == 1 ); // item 3 is the only selected item
CHECK( focused.GetCount() == 1 ); // because the focus changed from anchor to item 3
CHECK( selected.GetCount() == 2 ); // item 3 was selected twice
CHECK( deselected.GetCount() == 2 ); // anchor and item 3 were each deselected once
#endif // wxUSE_UIACTIONSIMULATOR
}
void ListBaseTestCase::ItemClick()
{
#if wxUSE_UIACTIONSIMULATOR
if ( !EnableUITests() )
return;
#ifdef __WXMSW__
// FIXME: This test fails on MSW buildbot slaves although works fine on
// development machine, no idea why. It seems to be a problem with
// wxUIActionSimulator rather the wxListCtrl control itself however.
if ( IsAutomaticTest() )
return;
#endif // __WXMSW__
wxListCtrl* const list = GetList();
list->InsertColumn(0, "Column 0", wxLIST_FORMAT_LEFT, 60);
list->InsertColumn(1, "Column 1", wxLIST_FORMAT_LEFT, 50);
list->InsertColumn(2, "Column 2", wxLIST_FORMAT_LEFT, 40);
list->InsertItem(0, "Item 0");
list->SetItem(0, 1, "first column");
list->SetItem(0, 2, "second column");
EventCounter selected(list, wxEVT_LIST_ITEM_SELECTED);
EventCounter focused(list, wxEVT_LIST_ITEM_FOCUSED);
EventCounter activated(list, wxEVT_LIST_ITEM_ACTIVATED);
EventCounter rclick(list, wxEVT_LIST_ITEM_RIGHT_CLICK);
EventCounter deselected(list, wxEVT_LIST_ITEM_DESELECTED);
wxUIActionSimulator sim;
wxRect pos;
list->GetItemRect(0, pos);
//We move in slightly so we are not on the edge
wxPoint point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
sim.MouseMove(point);
wxYield();
sim.MouseClick();
wxYield();
sim.MouseDblClick();
wxYield();
sim.MouseClick(wxMOUSE_BTN_RIGHT);
wxYield();
// We want a point within the listctrl but below any items
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 50);
sim.MouseMove(point);
wxYield();
sim.MouseClick();
wxYield();
// when the first item was selected the focus changes to it, but not
// on subsequent clicks
CHECK( focused.GetCount() == 1 );
CHECK( selected.GetCount() == 1 );
CHECK( deselected.GetCount() == 1 );
CHECK( activated.GetCount() == 1 );
CHECK( rclick.GetCount() == 1 );
#endif // wxUSE_UIACTIONSIMULATOR
}
void ListBaseTestCase::KeyDown()
{
#if wxUSE_UIACTIONSIMULATOR
if ( !EnableUITests() )
return;
wxListCtrl* const list = GetList();
EventCounter keydown(list, wxEVT_LIST_KEY_DOWN);
wxUIActionSimulator sim;
list->SetFocus();
wxYield();
sim.Text("aAbB"); // 4 letters + 2 shift mods.
wxYield();
CHECK( keydown.GetCount() == 6 );
#endif
}
void ListBaseTestCase::DeleteItems()
{
#ifndef __WXOSX__
wxListCtrl* const list = GetList();
EventCounter deleteitem(list, wxEVT_LIST_DELETE_ITEM);
EventCounter deleteall(list, wxEVT_LIST_DELETE_ALL_ITEMS);
list->InsertColumn(0, "Column 0", wxLIST_FORMAT_LEFT, 60);
list->InsertColumn(1, "Column 1", wxLIST_FORMAT_LEFT, 50);
list->InsertColumn(2, "Column 2", wxLIST_FORMAT_LEFT, 40);
list->InsertItem(0, "Item 0");
list->InsertItem(1, "Item 1");
list->InsertItem(2, "Item 1");
list->DeleteItem(0);
list->DeleteItem(0);
list->DeleteAllItems();
//Add some new items to tests ClearAll with
list->InsertColumn(0, "Column 0");
list->InsertItem(0, "Item 0");
list->InsertItem(1, "Item 1");
//Check that ClearAll actually sends a DELETE_ALL_ITEMS event
list->ClearAll();
//ClearAll and DeleteAllItems shouldn't send an event if there was nothing
//to clear
list->ClearAll();
list->DeleteAllItems();
CHECK( deleteitem.GetCount() == 2 );
CHECK( deleteall.GetCount() == 2 );
#endif
}
void ListBaseTestCase::InsertItem()
{
wxListCtrl* const list = GetList();
EventCounter insert(list, wxEVT_LIST_INSERT_ITEM);
list->InsertColumn(0, "Column 0", wxLIST_FORMAT_LEFT, 60);
wxListItem item;
item.SetId(0);
item.SetText("some text");
list->InsertItem(item);
list->InsertItem(1, "more text");
CHECK( insert.GetCount() == 2 );
}
void ListBaseTestCase::Find()
{
wxListCtrl* const list = GetList();
// set up for the test
list->InsertColumn(0, "Column 0");
list->InsertColumn(1, "Column 1");
list->InsertItem(0, "Item 0");
list->SetItem(0, 1, "first column");
list->InsertItem(1, "Item 1");
list->SetItem(1, 1, "first column");
list->InsertItem(2, "Item 40");
list->SetItem(2, 1, "first column");
list->InsertItem(3, "ITEM 01");
list->SetItem(3, 1, "first column");
CHECK( list->FindItem(-1, "Item 1") == 1 );
CHECK( list->FindItem(-1, "Item 4", true) == 2 );
CHECK( list->FindItem(1, "Item 40") == 2 );
CHECK( list->FindItem(2, "Item 0", true) == 3 );
}
void ListBaseTestCase::Visible()
{
wxListCtrl* const list = GetList();
list->InsertColumn(0, "Column 0");
list->InsertItem(0, wxString::Format("string 0"));
int count = list->GetCountPerPage();
for( int i = 1; i < count + 10; i++ )
{
list->InsertItem(i, wxString::Format("string %d", i));
}
CHECK( list->GetItemCount() == count + 10 );
CHECK( list->GetTopItem() == 0 );
CHECK(list->IsVisible(0));
CHECK(!list->IsVisible(count + 1));
CHECK(list->EnsureVisible(count + 9));
CHECK(list->IsVisible(count + 9));
CHECK(!list->IsVisible(9));
CHECK(list->GetTopItem() != 0);
}
void ListBaseTestCase::ItemFormatting()
{
wxListCtrl* const list = GetList();
list->InsertColumn(0, "Column 0");
list->InsertItem(0, "Item 0");
list->InsertItem(1, "Item 1");
list->InsertItem(2, "Item 2");
list->SetTextColour(*wxYELLOW);
list->SetBackgroundColour(*wxGREEN);
list->SetItemTextColour(0, *wxRED);
list->SetItemBackgroundColour(1, *wxBLUE);
CHECK( list->GetBackgroundColour() == *wxGREEN );
CHECK( list->GetItemBackgroundColour(1) == *wxBLUE );
CHECK( list->GetTextColour() == *wxYELLOW );
CHECK( list->GetItemTextColour(0) == *wxRED );
}
void ListBaseTestCase::EditLabel()
{
#if wxUSE_UIACTIONSIMULATOR
if ( !EnableUITests() )
return;
wxListCtrl* const list = GetList();
list->SetWindowStyleFlag(wxLC_REPORT | wxLC_EDIT_LABELS);
list->InsertColumn(0, "Column 0");
list->InsertItem(0, "Item 0");
list->InsertItem(1, "Item 1");
EventCounter beginedit(list, wxEVT_LIST_BEGIN_LABEL_EDIT);
EventCounter endedit(list, wxEVT_LIST_END_LABEL_EDIT);
wxUIActionSimulator sim;
list->EditLabel(0);
wxYield();
sim.Text("sometext");
wxYield();
sim.Char(WXK_RETURN);
wxYield();
CHECK( beginedit.GetCount() == 1 );
CHECK( endedit.GetCount() == 1 );
#endif
}
void ListBaseTestCase::ImageList()
{
wxListCtrl* const list = GetList();
wxSize size(32, 32);
wxImageList* imglist = new wxImageList(size.x, size.y);
imglist->Add(wxArtProvider::GetIcon(wxART_INFORMATION, wxART_OTHER, size));
imglist->Add(wxArtProvider::GetIcon(wxART_QUESTION, wxART_OTHER, size));
imglist->Add(wxArtProvider::GetIcon(wxART_WARNING, wxART_OTHER, size));
list->AssignImageList(imglist, wxIMAGE_LIST_NORMAL);
CHECK( list->GetImageList(wxIMAGE_LIST_NORMAL) == imglist );
}
void ListBaseTestCase::HitTest()
{
#ifdef __WXMSW__ // ..until proven to work with other platforms
wxListCtrl* const list = GetList();
list->SetWindowStyle(wxLC_REPORT);
// set small image list
wxSize size(16, 16);
wxImageList* m_imglistSmall = new wxImageList(size.x, size.y);
m_imglistSmall->Add(wxArtProvider::GetIcon(wxART_INFORMATION, wxART_LIST, size));
list->AssignImageList(m_imglistSmall, wxIMAGE_LIST_SMALL);
// insert 2 columns
list->InsertColumn(0, "Column 0");
list->InsertColumn(1, "Column 1");
// and a couple of test items too
list->InsertItem(0, "Item 0", 0);
list->SetItem(0, 1, "0, 1");
list->InsertItem(1, "Item 1", 0);
// enable checkboxes to test state icon
list->EnableCheckBoxes();
// get coordinates
wxRect rectSubItem0, rectIcon;
list->GetSubItemRect(0, 0, rectSubItem0); // column 0
list->GetItemRect(0, rectIcon, wxLIST_RECT_ICON); // icon
int y = rectSubItem0.GetTop() + (rectSubItem0.GetBottom() -
rectSubItem0.GetTop()) / 2;
int flags = 0;
// state icon (checkbox)
int xCheckBox = rectSubItem0.GetLeft() + (rectIcon.GetLeft() -
rectSubItem0.GetLeft()) / 2;
list->HitTest(wxPoint(xCheckBox, y), flags);
CHECK( flags == wxLIST_HITTEST_ONITEMSTATEICON );
// icon
int xIcon = rectIcon.GetLeft() + (rectIcon.GetRight() - rectIcon.GetLeft()) / 2;
list->HitTest(wxPoint(xIcon, y), flags);
CHECK( flags == wxLIST_HITTEST_ONITEMICON );
// label, beyond column 0
wxRect rectItem;
list->GetItemRect(0, rectItem); // entire item
int xHit = rectSubItem0.GetRight() + (rectItem.GetRight() - rectSubItem0.GetRight()) / 2;
list->HitTest(wxPoint(xHit, y), flags);
CHECK( flags == wxLIST_HITTEST_ONITEMLABEL );
#endif // __WXMSW__
}
namespace
{
//From the sample but fixed so it actually inverts
int wxCALLBACK
MyCompareFunction(wxIntPtr item1, wxIntPtr item2, wxIntPtr WXUNUSED(sortData))
{
// inverse the order
if (item1 < item2)
return 1;
if (item1 > item2)
return -1;
return 0;
}
}
void ListBaseTestCase::Sort()
{
wxListCtrl* const list = GetList();
list->InsertColumn(0, "Column 0");
list->InsertItem(0, "Item 0");
list->SetItemData(0, 0);
list->InsertItem(1, "Item 1");
list->SetItemData(1, 1);
list->SortItems(MyCompareFunction, 0);
CHECK( list->GetItemText(0) == "Item 1" );
CHECK( list->GetItemText(1) == "Item 0" );
}
#endif //wxUSE_LISTCTRL

View File

@@ -0,0 +1,74 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/listbasetest.cpp
// Purpose: Common wxListCtrl and wxListView tests
// Author: Steven Lamerton
// Created: 2010-07-20
// Copyright: (c) 2008,2025 Vadim Zeitlin <vadim@wxwidgets.org>,
// (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_TESTS_CONTROLS_LISTBASETEST_H_
#define _WX_TESTS_CONTROLS_LISTBASETEST_H_
class ListBaseTestCase
{
public:
ListBaseTestCase() { }
virtual ~ListBaseTestCase() { }
protected:
virtual wxListCtrl *GetList() const = 0;
void ColumnsOrder();
void ItemRect();
void ItemText();
void ChangeMode();
void MultiSelect();
void ItemClick();
void KeyDown();
void DeleteItems();
void InsertItem();
void Find();
void Visible();
void ItemFormatting();
void EditLabel();
void ImageList();
void HitTest();
void Sort();
wxDECLARE_NO_COPY_CLASS(ListBaseTestCase);
};
// In the macros below, ClassName is the name of the class (without "wx"
// prefix), i.e. an identifier, and ClassTag is the string containing the
// tag to be used in the test registration macro.
// Define a test case delegating to ListBaseTestCase.
#define wxLIST_TEST_CASE(ClassName, ClassTag, TestName) \
TEST_CASE_METHOD(ClassName ## TestCase, \
#ClassName "::" #TestName, \
ClassTag) \
{ \
TestName(); \
}
// Define all common test cases.
#define wxLIST_BASE_TESTS(ClassName, TagName) \
wxLIST_TEST_CASE(ClassName, TagName, ColumnsOrder) \
wxLIST_TEST_CASE(ClassName, TagName, ItemRect) \
wxLIST_TEST_CASE(ClassName, TagName, ItemText) \
wxLIST_TEST_CASE(ClassName, TagName, ChangeMode) \
wxLIST_TEST_CASE(ClassName, TagName, ItemClick) \
wxLIST_TEST_CASE(ClassName, TagName, KeyDown) \
wxLIST_TEST_CASE(ClassName, TagName, MultiSelect) \
wxLIST_TEST_CASE(ClassName, TagName, DeleteItems) \
wxLIST_TEST_CASE(ClassName, TagName, InsertItem) \
wxLIST_TEST_CASE(ClassName, TagName, Find) \
wxLIST_TEST_CASE(ClassName, TagName, Visible) \
wxLIST_TEST_CASE(ClassName, TagName, ItemFormatting) \
wxLIST_TEST_CASE(ClassName, TagName, EditLabel) \
wxLIST_TEST_CASE(ClassName, TagName, ImageList) \
wxLIST_TEST_CASE(ClassName, TagName, HitTest) \
wxLIST_TEST_CASE(ClassName, TagName, Sort)
#endif

View File

@@ -0,0 +1,81 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/listbooktest.cpp
// Purpose: wxListbook unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_LISTBOOK
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/listbook.h"
#include "wx/listctrl.h"
#include "bookctrlbasetest.h"
class ListbookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase
{
public:
ListbookTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxBookCtrlBase *GetBase() const override { return m_listbook; }
virtual wxEventType GetChangedEvent() const override
{ return wxEVT_LISTBOOK_PAGE_CHANGED; }
virtual wxEventType GetChangingEvent() const override
{ return wxEVT_LISTBOOK_PAGE_CHANGING; }
virtual bool HasBrokenMnemonics() const override { return true; }
CPPUNIT_TEST_SUITE( ListbookTestCase );
wxBOOK_CTRL_BASE_TESTS();
CPPUNIT_TEST( ListView );
CPPUNIT_TEST_SUITE_END();
void ListView();
wxListbook *m_listbook;
wxDECLARE_NO_COPY_CLASS(ListbookTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( ListbookTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ListbookTestCase, "ListbookTestCase" );
void ListbookTestCase::setUp()
{
m_listbook = new wxListbook(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(400, 300));
AddPanels();
}
void ListbookTestCase::tearDown()
{
wxDELETE(m_listbook);
}
void ListbookTestCase::ListView()
{
wxListView* listview = m_listbook->GetListView();
CPPUNIT_ASSERT(listview);
CPPUNIT_ASSERT_EQUAL(3, listview->GetItemCount());
CPPUNIT_ASSERT_EQUAL("Panel 1", listview->GetItemText(0));
}
#endif //wxUSE_LISTBOOK

View File

@@ -0,0 +1,292 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/listbox.cpp
// Purpose: wxListBox unit test
// Author: Steven Lamerton
// Created: 2010-06-29
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_LISTBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/listbox.h"
#endif // WX_PRECOMP
#include "itemcontainertest.h"
#include "testableframe.h"
#include "wx/uiaction.h"
class ListBoxTestCase : public ItemContainerTestCase, public CppUnit::TestCase
{
public:
ListBoxTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxItemContainer *GetContainer() const override { return m_list; }
virtual wxWindow *GetContainerWindow() const override { return m_list; }
CPPUNIT_TEST_SUITE( ListBoxTestCase );
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Sort );
CPPUNIT_TEST( MultipleSelect );
WXUISIM_TEST( ClickEvents );
WXUISIM_TEST( ClickNotOnItem );
CPPUNIT_TEST( HitTest );
//We also run all tests as an ownerdrawn list box. We do not need to
//run the wxITEM_CONTAINER_TESTS as they are tested with wxCheckListBox
#ifdef __WXMSW__
CPPUNIT_TEST( PseudoTest_OwnerDrawn );
CPPUNIT_TEST( Sort );
CPPUNIT_TEST( MultipleSelect );
WXUISIM_TEST( ClickEvents );
WXUISIM_TEST( ClickNotOnItem );
CPPUNIT_TEST( HitTest );
#endif
CPPUNIT_TEST_SUITE_END();
void Sort();
void MultipleSelect();
void ClickEvents();
void ClickNotOnItem();
void HitTest();
void PseudoTest_OwnerDrawn() { ms_ownerdrawn = true; }
static bool ms_ownerdrawn;
wxListBox* m_list;
wxDECLARE_NO_COPY_CLASS(ListBoxTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(ListBoxTestCase,
"[ListBoxTestCase][item-container]");
//initialise the static variable
bool ListBoxTestCase::ms_ownerdrawn = false;
void ListBoxTestCase::setUp()
{
if( ms_ownerdrawn )
{
m_list = new wxListBox(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(300, 200), 0, nullptr,
wxLB_OWNERDRAW);
}
else
{
m_list = new wxListBox(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(300, 200));
}
}
void ListBoxTestCase::tearDown()
{
wxDELETE(m_list);
}
void ListBoxTestCase::Sort()
{
#ifndef __WXOSX__
wxDELETE(m_list);
m_list = new wxListBox(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize, 0, nullptr,
wxLB_SORT);
wxArrayString testitems;
testitems.Add("aaa");
testitems.Add("Aaa");
testitems.Add("aba");
testitems.Add("aaab");
testitems.Add("aab");
testitems.Add("AAA");
m_list->Append(testitems);
#ifndef __WXQT__
CPPUNIT_ASSERT_EQUAL("AAA", m_list->GetString(0));
CPPUNIT_ASSERT_EQUAL("Aaa", m_list->GetString(1));
CPPUNIT_ASSERT_EQUAL("aaa", m_list->GetString(2));
CPPUNIT_ASSERT_EQUAL("aaab", m_list->GetString(3));
CPPUNIT_ASSERT_EQUAL("aab", m_list->GetString(4));
CPPUNIT_ASSERT_EQUAL("aba", m_list->GetString(5));
#else
CPPUNIT_ASSERT_EQUAL("aaa", m_list->GetString(0));
CPPUNIT_ASSERT_EQUAL("Aaa", m_list->GetString(1));
CPPUNIT_ASSERT_EQUAL("AAA", m_list->GetString(2));
CPPUNIT_ASSERT_EQUAL("aaab", m_list->GetString(3));
CPPUNIT_ASSERT_EQUAL("aab", m_list->GetString(4));
CPPUNIT_ASSERT_EQUAL("aba", m_list->GetString(5));
#endif
m_list->Append("a", wxUIntToPtr(1));
CPPUNIT_ASSERT_EQUAL("a", m_list->GetString(0));
CPPUNIT_ASSERT_EQUAL(wxUIntToPtr(1), m_list->GetClientData(0));
#endif
}
void ListBoxTestCase::MultipleSelect()
{
wxDELETE(m_list);
m_list = new wxListBox(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize, 0, nullptr,
wxLB_MULTIPLE);
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
testitems.Add("item 3");
m_list->Append(testitems);
m_list->SetSelection(0);
wxArrayInt selected;
m_list->GetSelections(selected);
CPPUNIT_ASSERT_EQUAL(1, selected.Count());
CPPUNIT_ASSERT_EQUAL(0, selected.Item(0));
m_list->SetSelection(2);
m_list->GetSelections(selected);
CPPUNIT_ASSERT_EQUAL(2, selected.Count());
CPPUNIT_ASSERT_EQUAL(2, selected.Item(1));
m_list->Deselect(0);
m_list->GetSelections(selected);
CPPUNIT_ASSERT_EQUAL(1, selected.Count());
CPPUNIT_ASSERT_EQUAL(2, selected.Item(0));
CPPUNIT_ASSERT(!m_list->IsSelected(0));
CPPUNIT_ASSERT(!m_list->IsSelected(1));
CPPUNIT_ASSERT(m_list->IsSelected(2));
CPPUNIT_ASSERT(!m_list->IsSelected(3));
m_list->SetSelection(0);
m_list->SetSelection(wxNOT_FOUND);
m_list->GetSelections(selected);
CPPUNIT_ASSERT_EQUAL(0, selected.Count());
}
void ListBoxTestCase::ClickEvents()
{
#if wxUSE_UIACTIONSIMULATOR
wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
wxTestableFrame);
EventCounter selected(frame, wxEVT_LISTBOX);
EventCounter dclicked(frame, wxEVT_LISTBOX_DCLICK);
wxUIActionSimulator sim;
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
m_list->Append(testitems);
m_list->Refresh();
m_list->Update();
sim.MouseMove(m_list->ClientToScreen(wxPoint(10, 10)));
wxYield();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, selected.GetCount());
sim.MouseDblClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, dclicked.GetCount());
#endif
}
void ListBoxTestCase::ClickNotOnItem()
{
#if wxUSE_UIACTIONSIMULATOR
wxTestableFrame* frame = wxStaticCast(wxTheApp->GetTopWindow(),
wxTestableFrame);
EventCounter selected(frame, wxEVT_LISTBOX);
EventCounter dclicked(frame, wxEVT_LISTBOX_DCLICK);
wxUIActionSimulator sim;
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
m_list->Append(testitems);
// It is important to set a valid selection: if the control doesn't have
// any, clicking anywhere in it, even outside of any item, selects the
// first item in the control under GTK resulting in a selection changed
// event. This is not a wx bug, just the native platform behaviour so
// simply avoid it by starting with a valid selection.
m_list->SetSelection(0);
m_list->Refresh();
m_list->Update();
sim.MouseMove(m_list->ClientToScreen(wxPoint(m_list->GetSize().x - 10, m_list->GetSize().y - 10)));
wxYield();
sim.MouseClick();
wxYield();
sim.MouseDblClick();
wxYield();
//If we are not clicking on an item we shouldn't have any events
CPPUNIT_ASSERT_EQUAL(0, selected.GetCount());
CPPUNIT_ASSERT_EQUAL(0, dclicked.GetCount());
#endif
}
void ListBoxTestCase::HitTest()
{
wxArrayString testitems;
testitems.Add("item 0");
testitems.Add("item 1");
testitems.Add("item 2");
m_list->Append(testitems);
#ifdef __WXGTK__
// The control needs to be realized for HitTest() to work.
wxYield();
#endif
wxPoint p(5, 5);
#ifdef __WXOSX__
// On macOS >= 11 wxListBox has a new layout because underlying
// NSTableView has a new style with padding so we need to move
// the point to be tested to another position.
if ( wxCheckOsVersion(11, 0) )
{
p = wxPoint(10, 10);
}
#endif
CPPUNIT_ASSERT_EQUAL( 0, m_list->HitTest(p) );
CPPUNIT_ASSERT_EQUAL( wxNOT_FOUND, m_list->HitTest(290, 190) );
}
#endif //wxUSE_LISTBOX

View File

@@ -0,0 +1,223 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/listctrltest.cpp
// Purpose: wxListCtrl unit test
// Author: Vadim Zeitlin
// Created: 2008-11-26
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
// (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_LISTCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/listctrl.h"
#include "wx/artprov.h"
#include "wx/imaglist.h"
#include "listbasetest.h"
#include "testableframe.h"
#include "wx/uiaction.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class ListCtrlTestCase : public ListBaseTestCase
{
public:
ListCtrlTestCase();
virtual ~ListCtrlTestCase() override;
virtual wxListCtrl *GetList() const override { return m_list; }
protected:
wxListCtrl *m_list;
wxDECLARE_NO_COPY_CLASS(ListCtrlTestCase);
};
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
ListCtrlTestCase::ListCtrlTestCase()
{
m_list = new wxListCtrl(wxTheApp->GetTopWindow());
m_list->SetWindowStyle(wxLC_REPORT | wxLC_EDIT_LABELS);
m_list->SetSize(400, 200);
wxTheApp->GetTopWindow()->Raise();
}
ListCtrlTestCase::~ListCtrlTestCase()
{
DeleteTestWindow(m_list);
}
wxLIST_BASE_TESTS(ListCtrl, "[listctrl]")
// Note that wxLIST_BASE_TESTS() already defines "ListCtrl::EditLabel" test.
TEST_CASE_METHOD(ListCtrlTestCase, "ListCtrl::CallEditLabel", "[listctrl]")
{
EventCounter editItem(m_list, wxEVT_LIST_BEGIN_LABEL_EDIT);
EventCounter endEditItem(m_list, wxEVT_LIST_END_LABEL_EDIT);
m_list->InsertColumn(0, "Column 0");
m_list->InsertItem(0, "foo");
m_list->EditLabel(0);
m_list->EndEditLabel(true);
CHECK(editItem.GetCount() == 1);
CHECK(endEditItem.GetCount() == 1);
}
TEST_CASE_METHOD(ListCtrlTestCase, "ListCtrl::SubitemRect", "[listctrl]")
{
wxBitmap bmp = wxArtProvider::GetBitmap(wxART_ERROR);
wxImageList* const iml = new wxImageList(bmp.GetWidth(), bmp.GetHeight());
iml->Add(bmp);
m_list->AssignImageList(iml, wxIMAGE_LIST_SMALL);
m_list->InsertColumn(0, "Column 0");
m_list->InsertColumn(1, "Column 1");
m_list->InsertColumn(2, "Column 2");
for ( int i = 0; i < 3; i++ )
{
long index = m_list->InsertItem(i, wxString::Format("This is item %d", i), 0);
m_list->SetItem(index, 1, wxString::Format("Column 1 item %d", i));
m_list->SetItem(index, 2, wxString::Format("Column 2 item %d", i));
}
wxRect rectLabel, rectIcon, rectItem;
// First check a subitem with an icon: it should have a valid icon
// rectangle and the label rectangle should be adjacent to it.
m_list->GetSubItemRect(1, 0, rectItem, wxLIST_RECT_BOUNDS);
m_list->GetSubItemRect(1, 0, rectIcon, wxLIST_RECT_ICON);
m_list->GetSubItemRect(1, 0, rectLabel, wxLIST_RECT_LABEL);
CHECK(!rectIcon.IsEmpty());
// Note that we can't use "==" here, in the native MSW version there is a
// gap between the item rectangle and the icon one.
CHECK(rectIcon.GetLeft() >= rectItem.GetLeft());
CHECK(rectLabel.GetLeft() == rectIcon.GetRight() + 1);
CHECK(rectLabel.GetRight() == rectItem.GetRight());
// For a subitem without an icon, label rectangle is the same one as the
// entire item one and the icon rectangle should be empty.
m_list->GetSubItemRect(1, 1, rectItem, wxLIST_RECT_BOUNDS);
m_list->GetSubItemRect(1, 1, rectIcon, wxLIST_RECT_ICON);
m_list->GetSubItemRect(1, 1, rectLabel, wxLIST_RECT_LABEL);
CHECK(rectIcon.IsEmpty());
// Here we can't check for exact equality either as there can be a margin.
CHECK(rectLabel.GetLeft() >= rectItem.GetLeft());
CHECK(rectLabel.GetRight() == rectItem.GetRight());
}
TEST_CASE_METHOD(ListCtrlTestCase, "ListCtrl::ColumnCount", "[listctrl]")
{
CHECK(m_list->GetColumnCount() == 0);
m_list->InsertColumn(0, "Column 0");
m_list->InsertColumn(1, "Column 1");
CHECK(m_list->GetColumnCount() == 2);
// Recreate the control in other modes to check the count there as well.
delete m_list;
m_list = new wxListCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxLC_LIST);
CHECK(m_list->GetColumnCount() == 1);
delete m_list;
m_list = new wxListCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxLC_ICON);
CHECK(m_list->GetColumnCount() == 0);
delete m_list;
m_list = new wxListCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxLC_SMALL_ICON);
CHECK(m_list->GetColumnCount() == 0);
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(ListCtrlTestCase, "ListCtrl::ColumnDrag", "[listctrl]")
{
if ( !EnableUITests() )
return;
EventCounter begindrag(m_list, wxEVT_LIST_COL_BEGIN_DRAG);
EventCounter dragging(m_list, wxEVT_LIST_COL_DRAGGING);
EventCounter enddrag(m_list, wxEVT_LIST_COL_END_DRAG);
m_list->InsertColumn(0, "Column 0");
m_list->InsertColumn(1, "Column 1");
m_list->InsertColumn(2, "Column 2");
m_list->Update();
m_list->SetFocus();
wxUIActionSimulator sim;
wxPoint pt = m_list->ClientToScreen(wxPoint(m_list->GetColumnWidth(0), 5));
sim.MouseMove(pt);
wxYield();
sim.MouseDown();
wxYield();
sim.MouseMove(pt.x + 50, pt.y);
wxYield();
sim.MouseUp();
wxYield();
CHECK( begindrag.GetCount() == 1 );
CHECK( dragging.GetCount() > 0 );
CHECK( enddrag.GetCount() == 1 );
m_list->ClearAll();
}
TEST_CASE_METHOD(ListCtrlTestCase, "ListCtrl::ColumnClick", "[listctrl]")
{
if ( !EnableUITests() )
return;
EventCounter colclick(m_list, wxEVT_LIST_COL_CLICK);
EventCounter colrclick(m_list, wxEVT_LIST_COL_RIGHT_CLICK);
m_list->InsertColumn(0, "Column 0", wxLIST_FORMAT_LEFT, 60);
wxUIActionSimulator sim;
sim.MouseMove(m_list->ClientToScreen(wxPoint(4, 4)));
wxYield();
sim.MouseClick();
sim.MouseClick(wxMOUSE_BTN_RIGHT);
wxYield();
CHECK( colclick.GetCount() == 1 );
CHECK( colrclick.GetCount() == 1 );
m_list->ClearAll();
}
#endif // wxUSE_UIACTIONSIMULATOR
#endif // wxUSE_LISTCTRL

View File

@@ -0,0 +1,123 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/listviewtest.cpp
// Purpose: wxListView unit test
// Author: Steven Lamerton
// Created: 2010-07-10
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_LISTCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/listctrl.h"
#include "listbasetest.h"
#include "testableframe.h"
class ListViewTestCase : public ListBaseTestCase
{
public:
ListViewTestCase();
virtual ~ListViewTestCase() override;
virtual wxListCtrl *GetList() const override { return m_list; }
protected:
wxListView *m_list;
wxDECLARE_NO_COPY_CLASS(ListViewTestCase);
};
ListViewTestCase::ListViewTestCase()
{
m_list = new wxListView(wxTheApp->GetTopWindow());
m_list->SetWindowStyle(wxLC_REPORT);
m_list->SetSize(400, 200);
}
ListViewTestCase::~ListViewTestCase()
{
DeleteTestWindow(m_list);
}
wxLIST_BASE_TESTS(ListView, "[listctrl][listview]")
TEST_CASE_METHOD(ListViewTestCase, "ListView::Selection", "[listctrl][listview]")
{
m_list->InsertColumn(0, "Column 0");
m_list->InsertItem(0, "Item 0");
m_list->InsertItem(1, "Item 1");
m_list->InsertItem(2, "Item 2");
m_list->InsertItem(3, "Item 3");
m_list->Select(0);
m_list->Select(2);
m_list->Select(3);
CHECK(m_list->IsSelected(0));
CHECK(!m_list->IsSelected(1));
long sel = m_list->GetFirstSelected();
CHECK( sel == 0 );
sel = m_list->GetNextSelected(sel);
CHECK( sel == 2 );
sel = m_list->GetNextSelected(sel);
CHECK( sel == 3 );
sel = m_list->GetNextSelected(sel);
CHECK( sel == -1 );
m_list->Select(0, false);
CHECK(!m_list->IsSelected(0));
CHECK( m_list->GetFirstSelected() == 2 );
}
TEST_CASE_METHOD(ListViewTestCase, "ListView::Focus", "[listctrl][listview]")
{
EventCounter focused(m_list, wxEVT_LIST_ITEM_FOCUSED);
m_list->InsertColumn(0, "Column 0");
m_list->InsertItem(0, "Item 0");
m_list->InsertItem(1, "Item 1");
m_list->InsertItem(2, "Item 2");
m_list->InsertItem(3, "Item 3");
CHECK( focused.GetCount() == 0 );
CHECK( m_list->GetFocusedItem() == -1 );
m_list->Focus(0);
CHECK( focused.GetCount() == 1 );
CHECK( m_list->GetFocusedItem() == 0 );
}
TEST_CASE_METHOD(ListViewTestCase, "ListView::AppendColumn", "[listctrl][listview]")
{
m_list->AppendColumn("Column 0");
m_list->AppendColumn("Column 1");
m_list->InsertItem(0, "First item");
m_list->SetItem(0, 1, "First subitem");
// Appending a column shouldn't change the existing items.
m_list->AppendColumn("Column 2");
CHECK( m_list->GetItemText(0) == "First item" );
CHECK( m_list->GetItemText(0, 1) == "First subitem" );
}
#endif

View File

@@ -0,0 +1,216 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/markup.cpp
// Purpose: wxMarkupParser and related classes unit tests
// Author: Vadim Zeitlin
// Created: 2011-02-17
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifndef WX_PRECOMP
#endif // WX_PRECOMP
#include "wx/private/markupparser.h"
class MarkupTestCase : public CppUnit::TestCase
{
public:
MarkupTestCase() { }
private:
CPPUNIT_TEST_SUITE( MarkupTestCase );
CPPUNIT_TEST( RoundTrip );
CPPUNIT_TEST( Quote );
CPPUNIT_TEST( Strip );
CPPUNIT_TEST_SUITE_END();
void RoundTrip();
void Quote();
void Strip();
wxDECLARE_NO_COPY_CLASS(MarkupTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( MarkupTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( MarkupTestCase, "MarkupTestCase" );
void MarkupTestCase::RoundTrip()
{
// Define a wxMarkupParserOutput object which produces the same markup
// string on output. This is, of course, perfectly useless, but allows us
// to test that parsing works as expected.
class RoundTripOutput : public wxMarkupParserOutput
{
public:
RoundTripOutput() { }
void Reset() { m_text.clear(); }
const wxString& GetText() const { return m_text; }
virtual void OnText(const wxString& text) override { m_text += text; }
virtual void OnBoldStart() override { m_text += "<b>"; }
virtual void OnBoldEnd() override { m_text += "</b>"; }
virtual void OnItalicStart() override { m_text += "<i>"; }
virtual void OnItalicEnd() override { m_text += "</i>"; }
virtual void OnUnderlinedStart() override { m_text += "<u>"; }
virtual void OnUnderlinedEnd() override { m_text += "</u>"; }
virtual void OnStrikethroughStart() override { m_text += "<s>"; }
virtual void OnStrikethroughEnd() override { m_text += "</s>"; }
virtual void OnBigStart() override { m_text += "<big>"; }
virtual void OnBigEnd() override { m_text += "</big>"; }
virtual void OnSmallStart() override { m_text += "<small>"; }
virtual void OnSmallEnd() override { m_text += "</small>"; }
virtual void OnTeletypeStart() override { m_text += "<tt>"; }
virtual void OnTeletypeEnd() override { m_text += "</tt>"; }
virtual void OnSpanStart(const wxMarkupSpanAttributes& attrs) override
{
m_text << "<span";
if ( !attrs.m_fgCol.empty() )
m_text << " foreground='" << attrs.m_fgCol << "'";
if ( !attrs.m_bgCol.empty() )
m_text << " background='" << attrs.m_bgCol << "'";
if ( !attrs.m_fontFace.empty() )
m_text << " face='" << attrs.m_fontFace << "'";
wxString size;
switch ( attrs.m_sizeKind )
{
case wxMarkupSpanAttributes::Size_Unspecified:
break;
case wxMarkupSpanAttributes::Size_Relative:
size << (attrs.m_fontSize > 0 ? "larger" : "smaller");
break;
case wxMarkupSpanAttributes::Size_Symbolic:
{
CPPUNIT_ASSERT( attrs.m_fontSize >= -3 );
CPPUNIT_ASSERT( attrs.m_fontSize <= 3 );
static const char *cssSizes[] =
{
"xx-small", "x-small", "small",
"medium",
"large", "x-large", "xx-large",
};
size << cssSizes[attrs.m_fontSize + 3];
}
break;
case wxMarkupSpanAttributes::Size_PointParts:
size.Printf("%u", attrs.m_fontSize);
break;
}
if ( !size.empty() )
m_text << " size='" << size << '\'';
// TODO: Handle the rest of attributes.
m_text << ">";
}
virtual void OnSpanEnd(const wxMarkupSpanAttributes& WXUNUSED(attrs)) override
{
m_text += "</span>";
}
private:
wxString m_text;
};
RoundTripOutput output;
wxMarkupParser parser(output);
#define CHECK_PARSES_OK(text) \
output.Reset(); \
CPPUNIT_ASSERT( parser.Parse(text) ); \
CPPUNIT_ASSERT_EQUAL( text, output.GetText() )
#define CHECK_PARSES_AS(text, result) \
output.Reset(); \
CPPUNIT_ASSERT( parser.Parse(text) ); \
CPPUNIT_ASSERT_EQUAL( result, output.GetText() )
#define CHECK_DOESNT_PARSE(text) \
CPPUNIT_ASSERT( !parser.Parse(text) )
CHECK_PARSES_OK( "" );
CHECK_PARSES_OK( "foo" );
CHECK_PARSES_OK( "foo<b>bar</b>" );
CHECK_PARSES_OK( "1<big>2<small>3</small>4<big>5</big></big>6" );
CHECK_PARSES_OK( "first <span foreground='red'>second</span> last" );
CHECK_PARSES_OK( "first <span foreground='red' "
"background='#ffffff'>second </span> last" );
CHECK_PARSES_OK( "<span size='10240'>10pt</span>" );
CHECK_PARSES_OK( "<span size='x-small'>much smaller</span>" );
CHECK_PARSES_OK( "<span size='larger'>larger</span>" );
CHECK_PARSES_OK
(
"<u>Please</u> notice: <i><b>any</b></i> <span foreground='grey'>"
"<s><tt>bugs</tt></s></span> in this code are <span foreground='red' "
"size='xx-large'>NOT</span> allowed."
);
CHECK_PARSES_OK( "foo&bar" );
CHECK_PARSES_AS( "foo&amp;bar", "foo&bar" );
CHECK_PARSES_AS( "&lt;O&apos;Reilly&gt;", "<O'Reilly>" );
CHECK_DOESNT_PARSE( "<" );
CHECK_DOESNT_PARSE( "<b" );
CHECK_DOESNT_PARSE( "<b>" );
CHECK_DOESNT_PARSE( "<b></i>" );
CHECK_DOESNT_PARSE( "<b><i></b></i>" );
CHECK_DOESNT_PARSE( "<foo></foo>" );
#undef CHECK_PARSES_OK
#undef CHECK_DOESNT_PARSE
}
void MarkupTestCase::Quote()
{
CPPUNIT_ASSERT_EQUAL( "", wxMarkupParser::Quote("") );
CPPUNIT_ASSERT_EQUAL( "foo", wxMarkupParser::Quote("foo") );
CPPUNIT_ASSERT_EQUAL( "&lt;foo&gt;", wxMarkupParser::Quote("<foo>") );
CPPUNIT_ASSERT_EQUAL( "B&amp;B", wxMarkupParser::Quote("B&B") );
CPPUNIT_ASSERT_EQUAL( "&quot;&quot;", wxMarkupParser::Quote("\"\"") );
}
void MarkupTestCase::Strip()
{
#define CHECK_STRIP( text, stripped ) \
CPPUNIT_ASSERT_EQUAL( stripped, wxMarkupParser::Strip(text) )
CHECK_STRIP( "", "" );
CHECK_STRIP( "foo", "foo" );
CHECK_STRIP( "&lt;foo&gt;", "<foo>" );
CHECK_STRIP( "<b>Big</b> problem", "Big problem" );
CHECK_STRIP( "<span foreground='red'>c</span>"
"<span background='green'>o</span>"
"<span background='blue'>l</span>"
"<span background='green'>o</span>"
"<span foreground='yellow'>u</span>"
"<span background='green'>r</span>",
"colour" );
#undef CHECK_STRIP
}

View File

@@ -0,0 +1,304 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/notebooktest.cpp
// Purpose: wxNotebook unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_NOTEBOOK
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/notebook.h"
#include "asserthelper.h"
#include "bookctrlbasetest.h"
#include "testableframe.h"
#include <memory>
class NotebookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase
{
public:
NotebookTestCase() { m_notebook = nullptr; m_numPageChanges = 0; }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxBookCtrlBase *GetBase() const override { return m_notebook; }
virtual wxEventType GetChangedEvent() const override
{ return wxEVT_NOTEBOOK_PAGE_CHANGED; }
virtual wxEventType GetChangingEvent() const override
{ return wxEVT_NOTEBOOK_PAGE_CHANGING; }
CPPUNIT_TEST_SUITE( NotebookTestCase );
wxBOOK_CTRL_BASE_TESTS();
CPPUNIT_TEST( Image );
CPPUNIT_TEST( RowCount );
CPPUNIT_TEST( NoEventsOnDestruction );
CPPUNIT_TEST( GetTabRect );
CPPUNIT_TEST( HitTestFlags );
CPPUNIT_TEST_SUITE_END();
void RowCount();
void NoEventsOnDestruction();
void GetTabRect();
void HitTestFlags();
void OnPageChanged(wxNotebookEvent&) { m_numPageChanges++; }
wxNotebook *m_notebook;
int m_numPageChanges;
wxDECLARE_NO_COPY_CLASS(NotebookTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( NotebookTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( NotebookTestCase, "NotebookTestCase" );
void NotebookTestCase::setUp()
{
m_notebook = new wxNotebook(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(400, 200));
AddPanels();
}
void NotebookTestCase::tearDown()
{
wxDELETE(m_notebook);
}
void NotebookTestCase::RowCount()
{
CPPUNIT_ASSERT_EQUAL(1, m_notebook->GetRowCount());
#ifdef __WXMSW__
wxDELETE(m_notebook);
m_notebook = new wxNotebook(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(400, 200),
wxNB_MULTILINE);
for( unsigned int i = 0; i < 10; i++ )
{
m_notebook->AddPage(new wxPanel(m_notebook), "Panel", false, 0);
}
CPPUNIT_ASSERT( m_notebook->GetRowCount() != 1 );
#endif
}
void NotebookTestCase::NoEventsOnDestruction()
{
// We can't use EventCounter helper here as it doesn't deal with the window
// it's connected to being destroyed during its life-time, so do it
// manually.
m_notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED,
&NotebookTestCase::OnPageChanged, this);
// Normally deleting a page before the selected one results in page
// selection changing and the corresponding event.
m_notebook->DeletePage(static_cast<size_t>(0));
CHECK( m_numPageChanges == 1 );
// But deleting the entire control shouldn't generate any events, yet it
// used to do under GTK+ 3 when a page different from the first one was
// selected.
m_notebook->ChangeSelection(1);
m_notebook->Destroy();
m_notebook = nullptr;
CHECK( m_numPageChanges == 1 );
}
TEST_CASE("wxNotebook::AddPageEvents", "[wxNotebook][AddPage][event]")
{
wxNotebook* const
notebook = new wxNotebook(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(400, 200));
std::unique_ptr<wxNotebook> cleanup(notebook);
CHECK( notebook->GetSelection() == wxNOT_FOUND );
EventCounter countPageChanging(notebook, wxEVT_NOTEBOOK_PAGE_CHANGING);
EventCounter countPageChanged(notebook, wxEVT_NOTEBOOK_PAGE_CHANGED);
// Add the first page, it is special.
notebook->AddPage(new wxPanel(notebook), "Initial page");
// The selection should have been changed.
CHECK( notebook->GetSelection() == 0 );
// But no events should have been generated.
CHECK( countPageChanging.GetCount() == 0 );
CHECK( countPageChanged.GetCount() == 0 );
// Add another page without selecting it.
notebook->AddPage(new wxPanel(notebook), "Unselected page");
// Selection shouldn't have changed.
CHECK( notebook->GetSelection() == 0 );
// And no events should have been generated, of course.
CHECK( countPageChanging.GetCount() == 0 );
CHECK( countPageChanged.GetCount() == 0 );
// Finally add another page and do select it.
notebook->AddPage(new wxPanel(notebook), "Selected page", true);
// It should have become selected.
CHECK( notebook->GetSelection() == 2 );
// And events for the selection change should have been generated.
CHECK( countPageChanging.GetCount() == 1 );
CHECK( countPageChanged.GetCount() == 1 );
}
void NotebookTestCase::GetTabRect()
{
wxNotebook *notebook = new wxNotebook(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(400, 200));
std::unique_ptr<wxNotebook> cleanup(notebook);
notebook->AddPage(new wxPanel(notebook), "Page");
// This function is only really implemented for wxMSW and wxUniv currently.
#if defined(__WXMSW__) || defined(__WXUNIVERSAL__)
// Create many pages, so that at least some of the are not visible.
for ( size_t i = 0; i < 30; i++ )
notebook->AddPage(new wxPanel(notebook), "Page");
const wxRect rectPage = notebook->GetTabRect(0);
REQUIRE(rectPage.width != 0);
REQUIRE(rectPage.height != 0);
int x = rectPage.x + rectPage.width;
for ( size_t i = 1; i < notebook->GetPageCount(); i++ )
{
wxRect r = notebook->GetTabRect(i);
if (wxIsRunningUnderWine())
{
// Wine behaves different than Windows. Windows reports the size of a
// tab even if it is not visible while Wine returns an empty rectangle.
if ( r == wxRect() )
{
WARN("Skipping test for pages after " << i << " under Wine.");
break;
}
}
INFO("Page #" << i << ": rect=" << r);
REQUIRE(r.x == x);
REQUIRE(r.y == rectPage.y);
REQUIRE(r.width == rectPage.width);
REQUIRE(r.height == rectPage.height);
x += r.width;
}
#else // !(__WXMSW__ || __WXUNIVERSAL__)
WX_ASSERT_FAILS_WITH_ASSERT( notebook->GetTabRect(0) );
#endif // ports
}
void NotebookTestCase::HitTestFlags()
{
std::unique_ptr<wxNotebook> notebook;
#if defined(__WXMSW__) || defined(__WXUNIVERSAL__)
long style = 0;
SECTION("Top") { style = wxBK_TOP; }
SECTION("Bottom") { style = wxBK_BOTTOM; }
SECTION("Left") { style = wxBK_LEFT; }
SECTION("Right") { style = wxBK_RIGHT; }
INFO("Style=" << style);
const bool isVertical = style == wxBK_TOP || style == wxBK_BOTTOM;
// HitTest() uses TCM_HITTEST for the vertical orientations and it doesn't
// seem to work correctly under Wine, so skip the test there (for the
// horizontal tabs we use our own code which does work even under Wine).
if ( isVertical && wxIsRunningUnderWine() )
return;
notebook.reset(new wxNotebook(wxTheApp->GetTopWindow(), wxID_ANY,
wxPoint(0, 0), wxSize(400, 200),
style));
// Simulate an icon of standard size, its contents doesn't matter.
const wxSize imageSize(16, 16);
wxBookCtrlBase::Images images;
images.push_back(wxBitmapBundle::FromBitmap(wxBitmap(imageSize)));
notebook->SetImages(images);
notebook->AddPage(new wxPanel(notebook.get()), "First Page", false, 0);
const wxRect r = notebook->GetTabRect(0);
INFO("Rect=" << r);
wxPoint pt;
if ( isVertical )
pt.y = r.y + r.height / 2;
else
pt.x = r.x + r.width / 2;
int nowhere = 0;
int onIcon = 0;
int onLabel = 0;
int onItem = 0;
const int d = isVertical ? r.width : r.height;
for (int i = 0; i < d; i++)
{
long flags = 0;
notebook->HitTest(pt, &flags);
if (flags & wxBK_HITTEST_NOWHERE)
nowhere++;
if (flags & wxBK_HITTEST_ONICON)
onIcon++;
if (flags & wxBK_HITTEST_ONLABEL)
onLabel++;
if (flags & wxBK_HITTEST_ONITEM)
onItem++;
if (isVertical)
pt.x++;
else
pt.y++;
}
CHECK(nowhere);
CHECK(onIcon);
CHECK(onLabel);
CHECK(onItem);
#else // !(__WXMSW__ || __WXUNIVERSAL__)
notebook.reset(new wxNotebook(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxSize(400, 200)));
notebook->AddPage(new wxPanel(notebook.get()), "First Page");
WX_ASSERT_FAILS_WITH_ASSERT(notebook->GetTabRect(0));
#endif // ports
}
#endif //wxUSE_NOTEBOOK

View File

@@ -0,0 +1,188 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/ownerdrawncomboboxtest.cpp
// Purpose: OwnerDrawnComboBox unit test
// Author: Jaakko Salli
// Created: 2010-12-17
// Copyright: (c) 2010 Jaakko Salli
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_ODCOMBOBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/odcombo.h"
#include "textentrytest.h"
#include "itemcontainertest.h"
#include "testableframe.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class OwnerDrawnComboBoxTestCase : public TextEntryTestCase,
public ItemContainerTestCase,
public CppUnit::TestCase
{
public:
OwnerDrawnComboBoxTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxTextEntry *GetTestEntry() const override { return m_combo; }
virtual wxWindow *GetTestWindow() const override { return m_combo; }
virtual wxItemContainer *GetContainer() const override { return m_combo; }
virtual wxWindow *GetContainerWindow() const override { return m_combo; }
virtual void CheckStringSelection(const char * WXUNUSED(sel)) override
{
// do nothing here, as explained in TextEntryTestCase comment, our
// GetStringSelection() is the wxChoice, not wxTextEntry, one and there
// is no way to return the selection contents directly
}
CPPUNIT_TEST_SUITE( OwnerDrawnComboBoxTestCase );
wxTEXT_ENTRY_TESTS();
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Size );
CPPUNIT_TEST( PopDismiss );
CPPUNIT_TEST( Sort );
CPPUNIT_TEST( ReadOnly );
CPPUNIT_TEST_SUITE_END();
void Size();
void PopDismiss();
void Sort();
void ReadOnly();
wxOwnerDrawnComboBox *m_combo;
wxDECLARE_NO_COPY_CLASS(OwnerDrawnComboBoxTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(OwnerDrawnComboBoxTestCase,
"[OwnerDrawnComboBoxTestCase][item-container]");
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void OwnerDrawnComboBoxTestCase::setUp()
{
m_combo = new wxOwnerDrawnComboBox(wxTheApp->GetTopWindow(), wxID_ANY);
}
void OwnerDrawnComboBoxTestCase::tearDown()
{
delete m_combo;
m_combo = nullptr;
}
// ----------------------------------------------------------------------------
// tests themselves
// ----------------------------------------------------------------------------
void OwnerDrawnComboBoxTestCase::Size()
{
// under MSW changing combobox size is a non-trivial operation because of
// confusion between the size of the control with and without dropdown, so
// check that it does work as expected
const int heightOrig = m_combo->GetSize().y;
// check that the height doesn't change if we don't touch it
m_combo->SetSize(100, -1);
CPPUNIT_ASSERT_EQUAL( heightOrig, m_combo->GetSize().y );
// check that setting both big and small (but not too small, there is a
// limit on how small the control can become under MSW) heights works
m_combo->SetSize(-1, 50);
CPPUNIT_ASSERT_EQUAL( 50, m_combo->GetSize().y );
m_combo->SetSize(-1, 10);
CPPUNIT_ASSERT_EQUAL( 10, m_combo->GetSize().y );
// and also that restoring it works (this used to be broken before 2.9.1)
m_combo->SetSize(-1, heightOrig);
CPPUNIT_ASSERT_EQUAL( heightOrig, m_combo->GetSize().y );
}
void OwnerDrawnComboBoxTestCase::PopDismiss()
{
EventCounter drop(m_combo, wxEVT_COMBOBOX_DROPDOWN);
EventCounter close(m_combo, wxEVT_COMBOBOX_CLOSEUP);
m_combo->Popup();
m_combo->Dismiss();
CPPUNIT_ASSERT_EQUAL(1, drop.GetCount());
CPPUNIT_ASSERT_EQUAL(1, close.GetCount());
}
void OwnerDrawnComboBoxTestCase::Sort()
{
delete m_combo;
m_combo = new wxOwnerDrawnComboBox(wxTheApp->GetTopWindow(),
wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
0, nullptr,
wxCB_SORT);
m_combo->Append("aaa");
m_combo->Append("Aaa");
m_combo->Append("aba");
m_combo->Append("aaab");
m_combo->Append("aab");
m_combo->Append("AAA");
CPPUNIT_ASSERT_EQUAL("AAA", m_combo->GetString(0));
CPPUNIT_ASSERT_EQUAL("Aaa", m_combo->GetString(1));
CPPUNIT_ASSERT_EQUAL("aaa", m_combo->GetString(2));
CPPUNIT_ASSERT_EQUAL("aaab", m_combo->GetString(3));
CPPUNIT_ASSERT_EQUAL("aab", m_combo->GetString(4));
CPPUNIT_ASSERT_EQUAL("aba", m_combo->GetString(5));
m_combo->Append("a");
CPPUNIT_ASSERT_EQUAL("a", m_combo->GetString(0));
}
void OwnerDrawnComboBoxTestCase::ReadOnly()
{
wxArrayString testitems;
testitems.Add("item 1");
testitems.Add("item 2");
delete m_combo;
m_combo = new wxOwnerDrawnComboBox(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
testitems,
wxCB_READONLY);
m_combo->SetValue("item 1");
CPPUNIT_ASSERT_EQUAL("item 1", m_combo->GetValue());
m_combo->SetValue("not an item");
CPPUNIT_ASSERT_EQUAL("item 1", m_combo->GetValue());
// Since this uses FindString it is case insensitive
m_combo->SetValue("ITEM 2");
CPPUNIT_ASSERT_EQUAL("item 2", m_combo->GetValue());
}
#endif // wxUSE_ODCOMBOBOX

View File

@@ -0,0 +1,72 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/pickerbasetest.cpp
// Purpose: wxPickerBase unit test
// Author: Steven Lamerton
// Created: 2010-08-07
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_COLOURPICKERCTRL || \
wxUSE_DIRPICKERCTRL || \
wxUSE_FILEPICKERCTRL || \
wxUSE_FONTPICKERCTRL
#include "wx/pickerbase.h"
#include "pickerbasetest.h"
void PickerBaseTestCase::Margin()
{
wxPickerBase* const base = GetBase();
CPPUNIT_ASSERT(base->HasTextCtrl());
CPPUNIT_ASSERT(base->GetInternalMargin() >= 0);
base->SetInternalMargin(15);
CPPUNIT_ASSERT_EQUAL(15, base->GetInternalMargin());
}
void PickerBaseTestCase::Proportion()
{
wxPickerBase* const base = GetBase();
CPPUNIT_ASSERT(base->HasTextCtrl());
base->SetPickerCtrlProportion(1);
base->SetTextCtrlProportion(1);
CPPUNIT_ASSERT_EQUAL(1, base->GetPickerCtrlProportion());
CPPUNIT_ASSERT_EQUAL(1, base->GetTextCtrlProportion());
}
void PickerBaseTestCase::Growable()
{
wxPickerBase* const base = GetBase();
CPPUNIT_ASSERT(base->HasTextCtrl());
base->SetPickerCtrlGrowable();
base->SetTextCtrlGrowable();
CPPUNIT_ASSERT(base->IsPickerCtrlGrowable());
CPPUNIT_ASSERT(base->IsTextCtrlGrowable());
base->SetPickerCtrlGrowable(false);
base->SetTextCtrlGrowable(false);
CPPUNIT_ASSERT(!base->IsPickerCtrlGrowable());
CPPUNIT_ASSERT(!base->IsTextCtrlGrowable());
}
void PickerBaseTestCase::Controls()
{
wxPickerBase* const base = GetBase();
CPPUNIT_ASSERT(base->HasTextCtrl());
CPPUNIT_ASSERT(base->GetTextCtrl() != nullptr);
CPPUNIT_ASSERT(base->GetPickerCtrl() != nullptr);
}
#endif

View File

@@ -0,0 +1,42 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/pickerbasetest.cpp
// Purpose: wxPickerBase unit test
// Author: Steven Lamerton
// Created: 2010-08-07
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_TESTS_CONTROLS_PICKERBASETEST_H_
#define _WX_TESTS_CONTROLS_PICKERBASETEST_H_
class PickerBaseTestCase
{
public:
PickerBaseTestCase() { }
virtual ~PickerBaseTestCase() { }
protected:
// this function must be overridden by the derived classes to return the
// text entry object we're testing, typically this is done by creating a
// control implementing wxPickerBase interface in setUp() virtual method and
// just returning it from here
virtual wxPickerBase *GetBase() const = 0;
// this should be inserted in the derived class CPPUNIT_TEST_SUITE
// definition to run all wxPickerBase tests as part of it
#define wxPICKER_BASE_TESTS() \
CPPUNIT_TEST( Margin ); \
CPPUNIT_TEST( Proportion ); \
CPPUNIT_TEST( Growable ); \
CPPUNIT_TEST( Controls )
void Margin();
void Proportion();
void Growable();
void Controls();
private:
wxDECLARE_NO_COPY_CLASS(PickerBaseTestCase);
};
#endif // _WX_TESTS_CONTROLS_PICKERBASETEST_H_

View File

@@ -0,0 +1,220 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/pickertest.cpp
// Purpose: Tests for various wxPickerBase based classes
// Author: Steven Lamerton
// Created: 2010-08-07
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_COLOURPICKERCTRL || \
wxUSE_DIRPICKERCTRL || \
wxUSE_FILEPICKERCTRL || \
wxUSE_FONTPICKERCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/clrpicker.h"
#include "wx/filepicker.h"
#include "wx/fontpicker.h"
#include "pickerbasetest.h"
#include "asserthelper.h"
#if wxUSE_COLOURPICKERCTRL
class ColourPickerCtrlTestCase : public PickerBaseTestCase,
public CppUnit::TestCase
{
public:
ColourPickerCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxPickerBase *GetBase() const override { return m_colour; }
CPPUNIT_TEST_SUITE( ColourPickerCtrlTestCase );
wxPICKER_BASE_TESTS();
CPPUNIT_TEST_SUITE_END();
wxColourPickerCtrl *m_colour;
wxDECLARE_NO_COPY_CLASS(ColourPickerCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( ColourPickerCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ColourPickerCtrlTestCase,
"ColourPickerCtrlTestCase" );
void ColourPickerCtrlTestCase::setUp()
{
m_colour = new wxColourPickerCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
*wxBLACK, wxDefaultPosition,
wxDefaultSize, wxCLRP_USE_TEXTCTRL);
}
void ColourPickerCtrlTestCase::tearDown()
{
wxDELETE(m_colour);
}
#endif //wxUSE_COLOURPICKERCTRL
#if wxUSE_DIRPICKERCTRL
class DirPickerCtrlTestCase : public PickerBaseTestCase,
public CppUnit::TestCase
{
public:
DirPickerCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxPickerBase *GetBase() const override { return m_dir; }
CPPUNIT_TEST_SUITE( DirPickerCtrlTestCase );
wxPICKER_BASE_TESTS();
CPPUNIT_TEST_SUITE_END();
wxDirPickerCtrl *m_dir;
wxDECLARE_NO_COPY_CLASS(DirPickerCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( DirPickerCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( DirPickerCtrlTestCase,
"DirPickerCtrlTestCase" );
void DirPickerCtrlTestCase::setUp()
{
m_dir = new wxDirPickerCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxEmptyString, wxDirSelectorPromptStr,
wxDefaultPosition, wxDefaultSize,
wxDIRP_USE_TEXTCTRL);
}
void DirPickerCtrlTestCase::tearDown()
{
wxDELETE(m_dir);
}
#endif //wxUSE_DIRPICKERCTRL
#if wxUSE_FILEPICKERCTRL
class FilePickerCtrlTestCase : public PickerBaseTestCase,
public CppUnit::TestCase
{
public:
FilePickerCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxPickerBase *GetBase() const override { return m_file; }
CPPUNIT_TEST_SUITE( FilePickerCtrlTestCase );
wxPICKER_BASE_TESTS();
CPPUNIT_TEST_SUITE_END();
wxFilePickerCtrl *m_file;
wxDECLARE_NO_COPY_CLASS(FilePickerCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( FilePickerCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FilePickerCtrlTestCase,
"FilePickerCtrlTestCase" );
void FilePickerCtrlTestCase::setUp()
{
m_file = new wxFilePickerCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxEmptyString, wxFileSelectorPromptStr,
wxFileSelectorDefaultWildcardStr,
wxDefaultPosition, wxDefaultSize,
wxFLP_USE_TEXTCTRL);
}
void FilePickerCtrlTestCase::tearDown()
{
wxDELETE(m_file);
}
#endif //wxUSE_FILEPICKERCTRL
#if wxUSE_FONTPICKERCTRL
class FontPickerCtrlTestCase : public PickerBaseTestCase,
public CppUnit::TestCase
{
public:
FontPickerCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxPickerBase *GetBase() const override { return m_font; }
CPPUNIT_TEST_SUITE( FontPickerCtrlTestCase );
wxPICKER_BASE_TESTS();
CPPUNIT_TEST( ColourSelection );
CPPUNIT_TEST_SUITE_END();
void ColourSelection();
wxFontPickerCtrl *m_font;
wxDECLARE_NO_COPY_CLASS(FontPickerCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( FontPickerCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( FontPickerCtrlTestCase,
"FontPickerCtrlTestCase" );
void FontPickerCtrlTestCase::setUp()
{
m_font = new wxFontPickerCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxNullFont, wxDefaultPosition, wxDefaultSize,
wxFNTP_USE_TEXTCTRL);
}
void FontPickerCtrlTestCase::tearDown()
{
wxDELETE(m_font);
}
void FontPickerCtrlTestCase::ColourSelection()
{
wxColour selectedColour(0xFF4269UL);
CHECK( m_font->GetSelectedColour() != selectedColour );
m_font->SetSelectedColour(selectedColour);
CPPUNIT_ASSERT_EQUAL_MESSAGE("Font picker did not react to color selection",
m_font->GetSelectedColour(), selectedColour);
}
#endif //wxUSE_FONTPICKERCTRL
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,211 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/radioboxtest.cpp
// Purpose: wxRadioBox unit test
// Author: Steven Lamerton
// Created: 2010-07-14
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_RADIOBOX
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/radiobox.h"
#endif // WX_PRECOMP
#include "wx/tooltip.h"
#include <memory>
class RadioBoxTestCase
{
protected:
RadioBoxTestCase();
~RadioBoxTestCase();
wxRadioBox* m_radio;
wxDECLARE_NO_COPY_CLASS(RadioBoxTestCase);
};
RadioBoxTestCase::RadioBoxTestCase()
{
wxArrayString choices;
choices.push_back("item 0");
choices.push_back("item 1");
choices.push_back("item 2");
m_radio = new wxRadioBox(wxTheApp->GetTopWindow(), wxID_ANY, "RadioBox",
wxDefaultPosition, wxDefaultSize, choices);
}
RadioBoxTestCase::~RadioBoxTestCase()
{
wxTheApp->GetTopWindow()->DestroyChildren();
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::FindString", "[radiobox][find]")
{
CHECK( m_radio->FindString("not here") == wxNOT_FOUND );
CHECK( m_radio->FindString("item 1") == 1 );
CHECK( m_radio->FindString("ITEM 2") == 2 );
CHECK( m_radio->FindString("ITEM 2", true) == wxNOT_FOUND );
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::RowColCount", "[radiobox]")
{
#ifndef __WXGTK__
wxArrayString choices;
choices.push_back("item 0");
choices.push_back("item 1");
choices.push_back("item 2");
m_radio = new wxRadioBox(wxTheApp->GetTopWindow(), wxID_ANY, "RadioBox",
wxDefaultPosition, wxDefaultSize, choices, 2);
CHECK( m_radio->GetColumnCount() == 2 );
CHECK( m_radio->GetRowCount() == 2 );
m_radio = new wxRadioBox(wxTheApp->GetTopWindow(), wxID_ANY, "RadioBox",
wxDefaultPosition, wxDefaultSize, choices, 1,
wxRA_SPECIFY_ROWS);
CHECK( m_radio->GetColumnCount() == 3 );
CHECK( m_radio->GetRowCount() == 1 );
#endif
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::Enable", "[radiobox][enable]")
{
#ifndef __WXOSX__
m_radio->Enable(false);
CHECK(!m_radio->IsItemEnabled(0));
m_radio->Enable(1, true);
CHECK(!m_radio->IsItemEnabled(0));
CHECK(m_radio->IsItemEnabled(1));
CHECK(!m_radio->IsItemEnabled(2));
m_radio->Enable(true);
CHECK(m_radio->IsItemEnabled(0));
CHECK(m_radio->IsItemEnabled(1));
CHECK(m_radio->IsItemEnabled(2));
m_radio->Enable(0, false);
CHECK(!m_radio->IsItemEnabled(0));
CHECK(m_radio->IsItemEnabled(1));
CHECK(m_radio->IsItemEnabled(2));
#endif
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::Show", "[radiobox][show]")
{
m_radio->Show(false);
CHECK(!m_radio->IsItemShown(0));
m_radio->Show(1, true);
CHECK(!m_radio->IsItemShown(0));
CHECK(m_radio->IsItemShown(1));
CHECK(!m_radio->IsItemShown(2));
m_radio->Show(true);
CHECK(m_radio->IsItemShown(0));
CHECK(m_radio->IsItemShown(1));
CHECK(m_radio->IsItemShown(2));
m_radio->Show(0, false);
CHECK(!m_radio->IsItemShown(0));
CHECK(m_radio->IsItemShown(1));
CHECK(m_radio->IsItemShown(2));
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::HelpText", "[radiobox][help]")
{
CHECK( m_radio->GetItemHelpText(0) == wxEmptyString );
m_radio->SetItemHelpText(1, "Item 1 help");
CHECK( m_radio->GetItemHelpText(1) == "Item 1 help" );
m_radio->SetItemHelpText(1, "");
CHECK( m_radio->GetItemHelpText(1) == wxEmptyString );
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::ToolTip", "[radiobox][tooltip]")
{
#if defined (__WXMSW__) || defined(__WXGTK__) || defined(__WXQT__)
//GetItemToolTip returns null if there is no tooltip set
CHECK(!m_radio->GetItemToolTip(0));
m_radio->SetItemToolTip(1, "Item 1 help");
CHECK( m_radio->GetItemToolTip(1)->GetTip() == "Item 1 help" );
m_radio->SetItemToolTip(1, "");
//However if we set a blank tip this does count as a tooltip
CHECK(!m_radio->GetItemToolTip(1));
#endif
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::Selection", "[radiobox][selection]")
{
//Until other item containers the first item is selected by default
CHECK( m_radio->GetSelection() == 0 );
CHECK( m_radio->GetStringSelection() == "item 0" );
m_radio->SetSelection(1);
CHECK( m_radio->GetSelection() == 1 );
CHECK( m_radio->GetStringSelection() == "item 1" );
m_radio->SetStringSelection("item 2");
CHECK( m_radio->GetSelection() == 2 );
CHECK( m_radio->GetStringSelection() == "item 2" );
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::Count", "[radiobox]")
{
//A trivial test for the item count as items can neither
//be added or removed
CHECK( m_radio->GetCount() == 3 );
CHECK(!m_radio->IsEmpty());
}
TEST_CASE_METHOD(RadioBoxTestCase, "RadioBox::SetString", "[radiobox]")
{
m_radio->SetString(0, "new item 0");
m_radio->SetString(2, "");
CHECK( m_radio->GetString(0) == "new item 0" );
CHECK( m_radio->GetString(2) == "" );
}
TEST_CASE("RadioBox::NoItems", "[radiobox]")
{
std::unique_ptr<wxRadioBox>
radio(new wxRadioBox(wxTheApp->GetTopWindow(), wxID_ANY, "Empty",
wxDefaultPosition, wxDefaultSize,
0, nullptr,
1, wxRA_SPECIFY_COLS));
CHECK( radio->GetCount() == 0 );
CHECK( radio->IsEmpty() );
CHECK_NOTHROW( radio->SetFocus() );
}
#endif // wxUSE_RADIOBOX

View File

@@ -0,0 +1,276 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/radiobuttontest.cpp
// Purpose: wxRadioButton unit test
// Author: Steven Lamerton
// Created: 2010-07-30
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_RADIOBTN
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/button.h"
#include "wx/panel.h"
#include "wx/radiobut.h"
#include "wx/sizer.h"
#include "wx/stattext.h"
#endif // WX_PRECOMP
#include "wx/uiaction.h"
#include "testableframe.h"
#include "testwindow.h"
#include <memory>
class RadioButtonTestCase
{
public:
RadioButtonTestCase();
~RadioButtonTestCase();
protected:
wxRadioButton* m_radio;
wxDECLARE_NO_COPY_CLASS(RadioButtonTestCase);
};
RadioButtonTestCase::RadioButtonTestCase()
{
m_radio = new wxRadioButton(wxTheApp->GetTopWindow(), wxID_ANY,
"wxRadioButton");
m_radio->Update();
m_radio->Refresh();
}
RadioButtonTestCase::~RadioButtonTestCase()
{
delete m_radio;
}
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Click", "[radiobutton]")
{
// OS X doesn't support selecting a single radio button
#if wxUSE_UIACTIONSIMULATOR && !defined(__WXOSX__)
EventCounter selected(m_radio, wxEVT_RADIOBUTTON);
wxUIActionSimulator sim;
wxYield();
sim.MouseMove(m_radio->GetScreenPosition() + wxPoint(10, 10));
sim.MouseClick();
wxYield();
CHECK(selected.GetCount() == 1);
#endif
}
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Value", "[radiobutton]")
{
#ifndef __WXGTK__
EventCounter selected(m_radio, wxEVT_RADIOBUTTON);
m_radio->SetValue(true);
CHECK(m_radio->GetValue());
m_radio->SetValue(false);
CHECK(!m_radio->GetValue());
CHECK(selected.GetCount() == 0);
#endif
}
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Group", "[radiobutton]")
{
wxWindow* const parent = wxTheApp->GetTopWindow();
// Create two different radio groups.
std::unique_ptr<wxRadioButton> g1radio0(new wxRadioButton(parent, wxID_ANY, "radio 1.0",
wxDefaultPosition, wxDefaultSize,
wxRB_GROUP));
std::unique_ptr<wxRadioButton> g1radio1(new wxRadioButton(parent, wxID_ANY, "radio 1.1"));
std::unique_ptr<wxRadioButton> g2radio0(new wxRadioButton(parent, wxID_ANY, "radio 2.0",
wxDefaultPosition, wxDefaultSize,
wxRB_GROUP));
std::unique_ptr<wxRadioButton> g2radio1(new wxRadioButton(parent, wxID_ANY, "radio 2.1"));
// Check that having another control between radio buttons doesn't break
// grouping.
std::unique_ptr<wxStaticText> text(new wxStaticText(parent, wxID_ANY, "Label"));
std::unique_ptr<wxRadioButton> g2radio2(new wxRadioButton(parent, wxID_ANY, "radio 2.2"));
g1radio0->SetValue(true);
g2radio0->SetValue(true);
CHECK(g1radio0->GetValue());
CHECK(!g1radio1->GetValue());
CHECK(g2radio0->GetValue());
CHECK(!g2radio1->GetValue());
g1radio1->SetValue(true);
g2radio1->SetValue(true);
CHECK(!g1radio0->GetValue());
CHECK(g1radio1->GetValue());
CHECK(!g2radio0->GetValue());
CHECK(g2radio1->GetValue());
g2radio2->SetValue(true);
CHECK(!g2radio0->GetValue());
CHECK(!g2radio1->GetValue());
CHECK(g2radio2->GetValue());
g1radio0->SetValue(true);
g2radio0->SetValue(true);
CHECK(g1radio0->GetValue());
CHECK(!g1radio1->GetValue());
CHECK(g2radio0->GetValue());
CHECK(!g2radio1->GetValue());
// Check that group navigation functions behave as expected.
// GetFirstInGroup()
CHECK_SAME_WINDOW(g1radio0->GetFirstInGroup(), g1radio0);
CHECK_SAME_WINDOW(g1radio1->GetFirstInGroup(), g1radio0);
CHECK_SAME_WINDOW(g2radio0->GetFirstInGroup(), g2radio0);
CHECK_SAME_WINDOW(g2radio1->GetFirstInGroup(), g2radio0);
CHECK_SAME_WINDOW(g2radio2->GetFirstInGroup(), g2radio0);
// GetLastInGroup()
CHECK_SAME_WINDOW(g1radio0->GetLastInGroup(), g1radio1);
CHECK_SAME_WINDOW(g1radio1->GetLastInGroup(), g1radio1);
CHECK_SAME_WINDOW(g2radio0->GetLastInGroup(), g2radio2);
CHECK_SAME_WINDOW(g2radio1->GetLastInGroup(), g2radio2);
CHECK_SAME_WINDOW(g2radio2->GetLastInGroup(), g2radio2);
// GetNextInGroup()
CHECK_SAME_WINDOW(g1radio0->GetNextInGroup(), g1radio1);
CHECK_SAME_WINDOW(g1radio1->GetNextInGroup(), nullptr);
CHECK_SAME_WINDOW(g2radio0->GetNextInGroup(), g2radio1);
CHECK_SAME_WINDOW(g2radio1->GetNextInGroup(), g2radio2);
CHECK_SAME_WINDOW(g2radio2->GetNextInGroup(), nullptr);
// GetPreviousInGroup()
CHECK_SAME_WINDOW(g1radio0->GetPreviousInGroup(), nullptr);
CHECK_SAME_WINDOW(g1radio1->GetPreviousInGroup(), g1radio0);
CHECK_SAME_WINDOW(g2radio0->GetPreviousInGroup(), nullptr);
CHECK_SAME_WINDOW(g2radio1->GetPreviousInGroup(), g2radio0);
CHECK_SAME_WINDOW(g2radio2->GetPreviousInGroup(), g2radio1);
}
TEST_CASE_METHOD(RadioButtonTestCase, "RadioButton::Single", "[radiobutton]")
{
//Create a group of 2 buttons, having second button selected
std::unique_ptr<wxRadioButton> gradio0(new wxRadioButton(wxTheApp->GetTopWindow(),
wxID_ANY, "wxRadioButton",
wxDefaultPosition,
wxDefaultSize, wxRB_GROUP));
std::unique_ptr<wxRadioButton> gradio1(new wxRadioButton(wxTheApp->GetTopWindow(),
wxID_ANY, "wxRadioButton"));
gradio1->SetValue(true);
//Create a "single" button (by default it will not be selected)
std::unique_ptr<wxRadioButton> sradio(new wxRadioButton(wxTheApp->GetTopWindow(),
wxID_ANY, "wxRadioButton",
wxDefaultPosition,
wxDefaultSize, wxRB_SINGLE));
//Create a non-grouped button and select it
std::unique_ptr<wxRadioButton> ngradio(new wxRadioButton(wxTheApp->GetTopWindow(),
wxID_ANY, "wxRadioButton"));
ngradio->SetValue(true);
//Select the "single" button
sradio->SetValue(true);
CHECK(gradio1->GetValue());
CHECK(ngradio->GetValue());
// Also check that navigation works as expected with "single" buttons.
CHECK_SAME_WINDOW(sradio->GetFirstInGroup(), sradio);
CHECK_SAME_WINDOW(sradio->GetLastInGroup(), sradio);
CHECK_SAME_WINDOW(sradio->GetPreviousInGroup(), nullptr);
CHECK_SAME_WINDOW(sradio->GetNextInGroup(), nullptr);
}
TEST_CASE("RadioButton::Focus", "[radiobutton][focus]")
{
// Create a container panel just to be able to destroy all the windows
// created here at once by simply destroying it.
wxWindow* const tlw = wxTheApp->GetTopWindow();
std::unique_ptr<wxPanel> parentPanel(new wxPanel(tlw));
// Create a panel containing 2 radio buttons and another control outside
// this panel, so that we could give focus to something different and then
// return it back to the panel.
wxPanel* const radioPanel = new wxPanel(parentPanel.get());
wxRadioButton* const radio1 = new wxRadioButton(radioPanel, wxID_ANY, "1");
wxRadioButton* const radio2 = new wxRadioButton(radioPanel, wxID_ANY, "2");
wxSizer* const radioSizer = new wxBoxSizer(wxHORIZONTAL);
radioSizer->Add(radio1);
radioSizer->Add(radio2);
radioPanel->SetSizer(radioSizer);
wxButton* const dummyButton = new wxButton(parentPanel.get(), wxID_OK);
wxSizer* const sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(radioPanel, wxSizerFlags(1).Expand());
sizer->Add(dummyButton, wxSizerFlags().Expand());
parentPanel->SetSizer(sizer);
parentPanel->SetSize(tlw->GetClientSize());
parentPanel->Layout();
// Initially the first radio button should be checked.
radio1->SetFocus();
CHECK(radio1->GetValue());
CHECK_FOCUS_IS(radio1);
// Switching focus from it shouldn't change this.
dummyButton->SetFocus();
CHECK(radio1->GetValue());
// Checking another radio button should make it checked and uncheck the
// first one.
radio2->SetValue(true);
CHECK(!radio1->GetValue());
CHECK(radio2->GetValue());
// While not changing focus.
CHECK_FOCUS_IS(dummyButton);
// And giving the focus to the panel shouldn't change radio button
// selection.
radioPanel->SetFocus();
// Under MSW, focus is always on the selected button, but in the other
// ports this is not necessarily the case, i.e. under wxGTK this check
// would fail because focus gets set to the first button -- even though the
// second one remains checked.
#ifdef __WXMSW__
CHECK_FOCUS_IS(radio2);
#endif
CHECK(!radio1->GetValue());
CHECK(radio2->GetValue());
}
#endif //wxUSE_RADIOBTN

View File

@@ -0,0 +1,158 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/rearrangelisttest.cpp
// Purpose: wxRearrangeList unit test
// Author: Steven Lamerton
// Created: 2010-07-05
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifndef __WXOSX_IPHONE__
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/rearrangectrl.h"
#include "itemcontainertest.h"
#include "testableframe.h"
class RearrangeListTestCase : public ItemContainerTestCase, public CppUnit::TestCase
{
public:
RearrangeListTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxItemContainer *GetContainer() const override { return m_rearrange; }
virtual wxWindow *GetContainerWindow() const override { return m_rearrange; }
CPPUNIT_TEST_SUITE( RearrangeListTestCase );
wxITEM_CONTAINER_TESTS();
CPPUNIT_TEST( Move );
CPPUNIT_TEST( MoveClientData );
CPPUNIT_TEST_SUITE_END();
void Move();
void MoveClientData();
wxRearrangeList* m_rearrange;
wxDECLARE_NO_COPY_CLASS(RearrangeListTestCase);
};
wxREGISTER_UNIT_TEST_WITH_TAGS(RearrangeListTestCase,
"[RearrangeListTestCase][item-container]");
void RearrangeListTestCase::setUp()
{
//We do not add items here as the wxITEM_CONTAINER_TESTS add their own
wxArrayInt order;
wxArrayString items;
m_rearrange = new wxRearrangeList(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize, order,
items);
}
void RearrangeListTestCase::tearDown()
{
wxDELETE(m_rearrange);
}
void RearrangeListTestCase::Move()
{
wxArrayInt order;
order.push_back(1);
order.push_back(~2);
order.push_back(0);
wxArrayString items;
items.push_back("first");
items.push_back("second");
items.push_back("third");
wxDELETE(m_rearrange);
m_rearrange = new wxRearrangeList(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize, order,
items);
//Confusingly setselection sets the physical item rather than the
//item specified in the constructor
m_rearrange->SetSelection(0);
CPPUNIT_ASSERT(!m_rearrange->CanMoveCurrentUp());
CPPUNIT_ASSERT(m_rearrange->CanMoveCurrentDown());
m_rearrange->SetSelection(1);
CPPUNIT_ASSERT(m_rearrange->CanMoveCurrentUp());
CPPUNIT_ASSERT(m_rearrange->CanMoveCurrentDown());
m_rearrange->SetSelection(2);
CPPUNIT_ASSERT(m_rearrange->CanMoveCurrentUp());
CPPUNIT_ASSERT(!m_rearrange->CanMoveCurrentDown());
m_rearrange->MoveCurrentUp();
m_rearrange->SetSelection(0);
m_rearrange->MoveCurrentDown();
wxArrayInt neworder = m_rearrange->GetCurrentOrder();
CPPUNIT_ASSERT_EQUAL(neworder[0], 0);
CPPUNIT_ASSERT_EQUAL(neworder[1], 1);
CPPUNIT_ASSERT_EQUAL(neworder[2], ~2);
CPPUNIT_ASSERT_EQUAL("first", m_rearrange->GetString(0));
CPPUNIT_ASSERT_EQUAL("second", m_rearrange->GetString(1));
CPPUNIT_ASSERT_EQUAL("third", m_rearrange->GetString(2));
}
void RearrangeListTestCase::MoveClientData()
{
wxArrayInt order;
order.push_back(0);
order.push_back(1);
order.push_back(2);
wxArrayString items;
items.push_back("first");
items.push_back("second");
items.push_back("third");
wxClientData* item0data = new wxStringClientData("item0data");
wxClientData* item1data = new wxStringClientData("item1data");
wxClientData* item2data = new wxStringClientData("item2data");
wxDELETE(m_rearrange);
m_rearrange = new wxRearrangeList(wxTheApp->GetTopWindow(), wxID_ANY,
wxDefaultPosition, wxDefaultSize, order,
items);
m_rearrange->SetClientObject(0, item0data);
m_rearrange->SetClientObject(1, item1data);
m_rearrange->SetClientObject(2, item2data);
m_rearrange->SetSelection(0);
m_rearrange->MoveCurrentDown();
m_rearrange->SetSelection(2);
m_rearrange->MoveCurrentUp();
CPPUNIT_ASSERT_EQUAL(item1data, m_rearrange->GetClientObject(0));
CPPUNIT_ASSERT_EQUAL(item2data, m_rearrange->GetClientObject(1));
CPPUNIT_ASSERT_EQUAL(item0data, m_rearrange->GetClientObject(2));
CPPUNIT_ASSERT_EQUAL("second", m_rearrange->GetString(0));
CPPUNIT_ASSERT_EQUAL("third", m_rearrange->GetString(1));
CPPUNIT_ASSERT_EQUAL("first", m_rearrange->GetString(2));
}
#endif

View File

@@ -0,0 +1,881 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/richtextctrltest.cpp
// Purpose: wxRichTextCtrl unit test
// Author: Steven Lamerton
// Created: 2010-07-07
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_RICHTEXT
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/richtext/richtextctrl.h"
#include "wx/richtext/richtextstyles.h"
#include "testableframe.h"
#include "asserthelper.h"
#include "wx/uiaction.h"
class RichTextCtrlTestCase : public CppUnit::TestCase
{
public:
RichTextCtrlTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( RichTextCtrlTestCase );
CPPUNIT_TEST( IsModified );
WXUISIM_TEST( CharacterEvent );
WXUISIM_TEST( DeleteEvent );
WXUISIM_TEST( ReturnEvent );
CPPUNIT_TEST( StyleEvent );
CPPUNIT_TEST( BufferResetEvent );
WXUISIM_TEST( UrlEvent );
WXUISIM_TEST( TextEvent );
CPPUNIT_TEST( CutCopyPaste );
CPPUNIT_TEST( UndoRedo );
CPPUNIT_TEST( CaretPosition );
CPPUNIT_TEST( Selection );
WXUISIM_TEST( Editable );
CPPUNIT_TEST( Range );
CPPUNIT_TEST( Alignment );
CPPUNIT_TEST( Bold );
CPPUNIT_TEST( Italic );
CPPUNIT_TEST( Underline );
CPPUNIT_TEST( Indent );
CPPUNIT_TEST( LineSpacing );
CPPUNIT_TEST( ParagraphSpacing );
CPPUNIT_TEST( TextColour );
CPPUNIT_TEST( NumberedBullet );
CPPUNIT_TEST( SymbolBullet );
CPPUNIT_TEST( FontSize );
CPPUNIT_TEST( Font );
CPPUNIT_TEST( Delete );
CPPUNIT_TEST( Url );
CPPUNIT_TEST( Table );
CPPUNIT_TEST_SUITE_END();
void IsModified();
void CharacterEvent();
void DeleteEvent();
void ReturnEvent();
void StyleEvent();
void BufferResetEvent();
void UrlEvent();
void TextEvent();
void CutCopyPaste();
void UndoRedo();
void CaretPosition();
void Selection();
void Editable();
void Range();
void Alignment();
void Bold();
void Italic();
void Underline();
void Indent();
void LineSpacing();
void ParagraphSpacing();
void TextColour();
void NumberedBullet();
void SymbolBullet();
void FontSize();
void Font();
void Delete();
void Url();
void Table();
wxRichTextCtrl* m_rich;
wxDECLARE_NO_COPY_CLASS(RichTextCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( RichTextCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( RichTextCtrlTestCase, "RichTextCtrlTestCase" );
void RichTextCtrlTestCase::setUp()
{
m_rich = new wxRichTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxSize(400, 200), wxWANTS_CHARS);
}
void RichTextCtrlTestCase::tearDown()
{
wxDELETE(m_rich);
}
void RichTextCtrlTestCase::IsModified()
{
CPPUNIT_ASSERT_EQUAL( false, m_rich->IsModified() );
m_rich->WriteText("abcdef");
CPPUNIT_ASSERT_EQUAL( true, m_rich->IsModified() );
}
void RichTextCtrlTestCase::CharacterEvent()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter character(m_rich, wxEVT_RICHTEXT_CHARACTER);
EventCounter content(m_rich, wxEVT_RICHTEXT_CONTENT_INSERTED);
m_rich->SetFocus();
wxUIActionSimulator sim;
sim.Text("abcdef");
wxYield();
CPPUNIT_ASSERT_EQUAL(6, character.GetCount());
CPPUNIT_ASSERT_EQUAL(6, content.GetCount());
character.Clear();
content.Clear();
//As these are not characters they shouldn't count
sim.Char(WXK_RETURN);
sim.Char(WXK_SHIFT);
wxYield();
CPPUNIT_ASSERT_EQUAL(0, character.GetCount());
CPPUNIT_ASSERT_EQUAL(1, content.GetCount());
#endif
}
void RichTextCtrlTestCase::DeleteEvent()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter deleteevent(m_rich, wxEVT_RICHTEXT_DELETE);
EventCounter contentdelete(m_rich, wxEVT_RICHTEXT_CONTENT_DELETED);
m_rich->SetFocus();
wxUIActionSimulator sim;
sim.Text("abcdef");
sim.Char(WXK_BACK);
sim.Char(WXK_DELETE);
wxYield();
CPPUNIT_ASSERT_EQUAL(2, deleteevent.GetCount());
//Only one as the delete doesn't delete anthing
CPPUNIT_ASSERT_EQUAL(1, contentdelete.GetCount());
#endif
}
void RichTextCtrlTestCase::ReturnEvent()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter returnevent(m_rich, wxEVT_RICHTEXT_RETURN);
m_rich->SetFocus();
wxUIActionSimulator sim;
sim.Char(WXK_RETURN);
wxYield();
CPPUNIT_ASSERT_EQUAL(1, returnevent.GetCount());
#endif
}
void RichTextCtrlTestCase::StyleEvent()
{
EventCounter stylechanged(m_rich, wxEVT_RICHTEXT_STYLE_CHANGED);
m_rich->SetValue("Sometext");
m_rich->SetStyle(0, 8, wxTextAttr(*wxRED, *wxWHITE));
CPPUNIT_ASSERT_EQUAL(1, stylechanged.GetCount());
}
void RichTextCtrlTestCase::BufferResetEvent()
{
EventCounter reset(m_rich, wxEVT_RICHTEXT_BUFFER_RESET);
m_rich->AppendText("more text!");
m_rich->SetValue("");
CPPUNIT_ASSERT_EQUAL(1, reset.GetCount());
reset.Clear();
m_rich->AppendText("more text!");
m_rich->Clear();
CPPUNIT_ASSERT_EQUAL(1, reset.GetCount());
reset.Clear();
//We expect a buffer reset here as setvalue clears the existing text
m_rich->SetValue("replace");
CPPUNIT_ASSERT_EQUAL(1, reset.GetCount());
}
void RichTextCtrlTestCase::UrlEvent()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter url(m_rich, wxEVT_TEXT_URL);
m_rich->BeginURL("http://www.wxwidgets.org");
m_rich->WriteText("http://www.wxwidgets.org");
m_rich->EndURL();
wxUIActionSimulator sim;
sim.MouseMove(m_rich->ClientToScreen(wxPoint(10, 10)));
wxYield();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, url.GetCount());
#endif
}
void RichTextCtrlTestCase::TextEvent()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter updated(m_rich, wxEVT_TEXT);
m_rich->SetFocus();
wxUIActionSimulator sim;
sim.Text("abcdef");
wxYield();
CPPUNIT_ASSERT_EQUAL("abcdef", m_rich->GetValue());
CPPUNIT_ASSERT_EQUAL(6, updated.GetCount());
#endif
}
void RichTextCtrlTestCase::CutCopyPaste()
{
#ifndef __WXOSX__
m_rich->AppendText("sometext");
m_rich->SelectAll();
if(m_rich->CanCut() && m_rich->CanPaste())
{
m_rich->Cut();
CPPUNIT_ASSERT(m_rich->IsEmpty());
wxYield();
m_rich->Paste();
CPPUNIT_ASSERT_EQUAL("sometext", m_rich->GetValue());
}
m_rich->SelectAll();
if(m_rich->CanCopy() && m_rich->CanPaste())
{
m_rich->Copy();
m_rich->Clear();
CPPUNIT_ASSERT(m_rich->IsEmpty());
wxYield();
m_rich->Paste();
CPPUNIT_ASSERT_EQUAL("sometext", m_rich->GetValue());
}
#endif
}
void RichTextCtrlTestCase::UndoRedo()
{
m_rich->AppendText("sometext");
CPPUNIT_ASSERT(m_rich->CanUndo());
m_rich->Undo();
CPPUNIT_ASSERT(m_rich->IsEmpty());
CPPUNIT_ASSERT(m_rich->CanRedo());
m_rich->Redo();
CPPUNIT_ASSERT_EQUAL("sometext", m_rich->GetValue());
m_rich->AppendText("Batch undo");
m_rich->SelectAll();
//Also test batch operations
m_rich->BeginBatchUndo("batchtest");
m_rich->ApplyBoldToSelection();
m_rich->ApplyItalicToSelection();
m_rich->EndBatchUndo();
CPPUNIT_ASSERT(m_rich->CanUndo());
m_rich->Undo();
CPPUNIT_ASSERT(!m_rich->IsSelectionBold());
CPPUNIT_ASSERT(!m_rich->IsSelectionItalics());
CPPUNIT_ASSERT(m_rich->CanRedo());
m_rich->Redo();
CPPUNIT_ASSERT(m_rich->IsSelectionBold());
CPPUNIT_ASSERT(m_rich->IsSelectionItalics());
//And surpressing undo
m_rich->BeginSuppressUndo();
m_rich->AppendText("Can't undo this");
CPPUNIT_ASSERT(m_rich->CanUndo());
m_rich->EndSuppressUndo();
}
void RichTextCtrlTestCase::CaretPosition()
{
m_rich->AddParagraph("This is paragraph one");
m_rich->AddParagraph("Paragraph two\n has \nlots of\n lines");
m_rich->SetInsertionPoint(2);
CPPUNIT_ASSERT_EQUAL(1, m_rich->GetCaretPosition());
m_rich->MoveToParagraphStart();
CPPUNIT_ASSERT_EQUAL(0, m_rich->GetCaretPosition());
m_rich->MoveRight();
m_rich->MoveRight(2);
m_rich->MoveLeft(1);
m_rich->MoveLeft(0);
CPPUNIT_ASSERT_EQUAL(2, m_rich->GetCaretPosition());
m_rich->MoveToParagraphEnd();
CPPUNIT_ASSERT_EQUAL(21, m_rich->GetCaretPosition());
m_rich->MoveToLineStart();
CPPUNIT_ASSERT_EQUAL(0, m_rich->GetCaretPosition());
m_rich->MoveToLineEnd();
CPPUNIT_ASSERT_EQUAL(21, m_rich->GetCaretPosition());
}
void RichTextCtrlTestCase::Selection()
{
m_rich->SetValue("some more text");
m_rich->SelectAll();
CPPUNIT_ASSERT_EQUAL("some more text", m_rich->GetStringSelection());
m_rich->SelectNone();
CPPUNIT_ASSERT_EQUAL("", m_rich->GetStringSelection());
m_rich->SelectWord(1);
CPPUNIT_ASSERT_EQUAL("some", m_rich->GetStringSelection());
m_rich->SetSelection(5, 14);
CPPUNIT_ASSERT_EQUAL("more text", m_rich->GetStringSelection());
wxRichTextRange range(5, 9);
m_rich->SetSelectionRange(range);
CPPUNIT_ASSERT_EQUAL("more", m_rich->GetStringSelection());
}
void RichTextCtrlTestCase::Editable()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter updated(m_rich, wxEVT_TEXT);
m_rich->SetFocus();
wxUIActionSimulator sim;
sim.Text("abcdef");
wxYield();
CPPUNIT_ASSERT_EQUAL("abcdef", m_rich->GetValue());
CPPUNIT_ASSERT_EQUAL(6, updated.GetCount());
updated.Clear();
m_rich->SetEditable(false);
sim.Text("gh");
wxYield();
CPPUNIT_ASSERT_EQUAL("abcdef", m_rich->GetValue());
CPPUNIT_ASSERT_EQUAL(0, updated.GetCount());
#endif
}
void RichTextCtrlTestCase::Range()
{
wxRichTextRange range(0, 10);
CPPUNIT_ASSERT_EQUAL(0, range.GetStart());
CPPUNIT_ASSERT_EQUAL(10, range.GetEnd());
CPPUNIT_ASSERT_EQUAL(11, range.GetLength());
CPPUNIT_ASSERT(range.Contains(5));
wxRichTextRange outside(12, 14);
CPPUNIT_ASSERT(outside.IsOutside(range));
wxRichTextRange inside(6, 7);
CPPUNIT_ASSERT(inside.IsWithin(range));
range.LimitTo(inside);
CPPUNIT_ASSERT(inside == range);
CPPUNIT_ASSERT(inside + range == outside);
CPPUNIT_ASSERT(outside - range == inside);
range.SetStart(4);
range.SetEnd(6);
CPPUNIT_ASSERT_EQUAL(4, range.GetStart());
CPPUNIT_ASSERT_EQUAL(6, range.GetEnd());
CPPUNIT_ASSERT_EQUAL(3, range.GetLength());
inside.SetRange(6, 4);
inside.Swap();
CPPUNIT_ASSERT(inside == range);
}
void RichTextCtrlTestCase::Alignment()
{
m_rich->SetValue("text to align");
m_rich->SelectAll();
m_rich->ApplyAlignmentToSelection(wxTEXT_ALIGNMENT_RIGHT);
CPPUNIT_ASSERT(m_rich->IsSelectionAligned(wxTEXT_ALIGNMENT_RIGHT));
m_rich->BeginAlignment(wxTEXT_ALIGNMENT_CENTRE);
m_rich->AddParagraph("middle aligned");
m_rich->EndAlignment();
m_rich->SetSelection(20, 25);
CPPUNIT_ASSERT(m_rich->IsSelectionAligned(wxTEXT_ALIGNMENT_CENTRE));
}
void RichTextCtrlTestCase::Bold()
{
m_rich->SetValue("text to bold");
m_rich->SelectAll();
m_rich->ApplyBoldToSelection();
CPPUNIT_ASSERT(m_rich->IsSelectionBold());
m_rich->BeginBold();
m_rich->AddParagraph("bold paragraph");
m_rich->EndBold();
m_rich->AddParagraph("not bold paragraph");
m_rich->SetSelection(15, 20);
CPPUNIT_ASSERT(m_rich->IsSelectionBold());
m_rich->SetSelection(30, 35);
CPPUNIT_ASSERT(!m_rich->IsSelectionBold());
}
void RichTextCtrlTestCase::Italic()
{
m_rich->SetValue("text to italic");
m_rich->SelectAll();
m_rich->ApplyItalicToSelection();
CPPUNIT_ASSERT(m_rich->IsSelectionItalics());
m_rich->BeginItalic();
m_rich->AddParagraph("italic paragraph");
m_rich->EndItalic();
m_rich->AddParagraph("not italic paragraph");
m_rich->SetSelection(20, 25);
CPPUNIT_ASSERT(m_rich->IsSelectionItalics());
m_rich->SetSelection(35, 40);
CPPUNIT_ASSERT(!m_rich->IsSelectionItalics());
}
void RichTextCtrlTestCase::Underline()
{
m_rich->SetValue("text to underline");
m_rich->SelectAll();
m_rich->ApplyUnderlineToSelection();
CPPUNIT_ASSERT(m_rich->IsSelectionUnderlined());
m_rich->BeginUnderline();
m_rich->AddParagraph("underline paragraph");
m_rich->EndUnderline();
m_rich->AddParagraph("not underline paragraph");
m_rich->SetSelection(20, 25);
CPPUNIT_ASSERT(m_rich->IsSelectionUnderlined());
m_rich->SetSelection(40, 45);
CPPUNIT_ASSERT(!m_rich->IsSelectionUnderlined());
}
void RichTextCtrlTestCase::Indent()
{
m_rich->BeginLeftIndent(12, -5);
m_rich->BeginRightIndent(14);
m_rich->AddParagraph("A paragraph with indents");
m_rich->EndLeftIndent();
m_rich->EndRightIndent();
m_rich->AddParagraph("No more indent");
wxTextAttr indent;
m_rich->GetStyle(5, indent);
CPPUNIT_ASSERT_EQUAL(12, indent.GetLeftIndent());
CPPUNIT_ASSERT_EQUAL(-5, indent.GetLeftSubIndent());
CPPUNIT_ASSERT_EQUAL(14, indent.GetRightIndent());
m_rich->GetStyle(35, indent);
CPPUNIT_ASSERT_EQUAL(0, indent.GetLeftIndent());
CPPUNIT_ASSERT_EQUAL(0, indent.GetLeftSubIndent());
CPPUNIT_ASSERT_EQUAL(0, indent.GetRightIndent());
}
void RichTextCtrlTestCase::LineSpacing()
{
m_rich->BeginLineSpacing(20);
m_rich->AddParagraph("double spaced");
m_rich->EndLineSpacing();
m_rich->BeginLineSpacing(wxTEXT_ATTR_LINE_SPACING_HALF);
m_rich->AddParagraph("1.5 spaced");
m_rich->EndLineSpacing();
m_rich->AddParagraph("normally spaced");
wxTextAttr spacing;
m_rich->GetStyle(5, spacing);
CPPUNIT_ASSERT_EQUAL(20, spacing.GetLineSpacing());
m_rich->GetStyle(20, spacing);
CPPUNIT_ASSERT_EQUAL(15, spacing.GetLineSpacing());
m_rich->GetStyle(30, spacing);
CPPUNIT_ASSERT_EQUAL(10, spacing.GetLineSpacing());
}
void RichTextCtrlTestCase::ParagraphSpacing()
{
m_rich->BeginParagraphSpacing(15, 20);
m_rich->AddParagraph("spaced paragraph");
m_rich->EndParagraphSpacing();
m_rich->AddParagraph("non-spaced paragraph");
wxTextAttr spacing;
m_rich->GetStyle(5, spacing);
CPPUNIT_ASSERT_EQUAL(15, spacing.GetParagraphSpacingBefore());
CPPUNIT_ASSERT_EQUAL(20, spacing.GetParagraphSpacingAfter());
m_rich->GetStyle(25, spacing);
//Make sure we test against the defaults
CPPUNIT_ASSERT_EQUAL(m_rich->GetBasicStyle().GetParagraphSpacingBefore(),
spacing.GetParagraphSpacingBefore());
CPPUNIT_ASSERT_EQUAL(m_rich->GetBasicStyle().GetParagraphSpacingAfter(),
spacing.GetParagraphSpacingAfter());
}
void RichTextCtrlTestCase::TextColour()
{
m_rich->BeginTextColour(*wxRED);
m_rich->AddParagraph("red paragraph");
m_rich->EndTextColour();
m_rich->AddParagraph("default paragraph");
wxTextAttr colour;
m_rich->GetStyle(5, colour);
CPPUNIT_ASSERT_EQUAL(*wxRED, colour.GetTextColour());
m_rich->GetStyle(25, colour);
CPPUNIT_ASSERT_EQUAL(m_rich->GetBasicStyle().GetTextColour(),
colour.GetTextColour());
}
void RichTextCtrlTestCase::NumberedBullet()
{
m_rich->BeginNumberedBullet(1, 15, 20);
m_rich->AddParagraph("bullet one");
m_rich->EndNumberedBullet();
m_rich->BeginNumberedBullet(2, 25, -5);
m_rich->AddParagraph("bullet two");
m_rich->EndNumberedBullet();
wxTextAttr bullet;
m_rich->GetStyle(5, bullet);
CPPUNIT_ASSERT(bullet.HasBulletStyle());
CPPUNIT_ASSERT(bullet.HasBulletNumber());
CPPUNIT_ASSERT_EQUAL(1, bullet.GetBulletNumber());
CPPUNIT_ASSERT_EQUAL(15, bullet.GetLeftIndent());
CPPUNIT_ASSERT_EQUAL(20, bullet.GetLeftSubIndent());
m_rich->GetStyle(15, bullet);
CPPUNIT_ASSERT(bullet.HasBulletStyle());
CPPUNIT_ASSERT(bullet.HasBulletNumber());
CPPUNIT_ASSERT_EQUAL(2, bullet.GetBulletNumber());
CPPUNIT_ASSERT_EQUAL(25, bullet.GetLeftIndent());
CPPUNIT_ASSERT_EQUAL(-5, bullet.GetLeftSubIndent());
}
void RichTextCtrlTestCase::SymbolBullet()
{
m_rich->BeginSymbolBullet("*", 15, 20);
m_rich->AddParagraph("bullet one");
m_rich->EndSymbolBullet();
m_rich->BeginSymbolBullet("%", 25, -5);
m_rich->AddParagraph("bullet two");
m_rich->EndSymbolBullet();
wxTextAttr bullet;
m_rich->GetStyle(5, bullet);
CPPUNIT_ASSERT(bullet.HasBulletStyle());
CPPUNIT_ASSERT(bullet.HasBulletText());
CPPUNIT_ASSERT_EQUAL("*", bullet.GetBulletText());
CPPUNIT_ASSERT_EQUAL(15, bullet.GetLeftIndent());
CPPUNIT_ASSERT_EQUAL(20, bullet.GetLeftSubIndent());
m_rich->GetStyle(15, bullet);
CPPUNIT_ASSERT(bullet.HasBulletStyle());
CPPUNIT_ASSERT(bullet.HasBulletText());
CPPUNIT_ASSERT_EQUAL("%", bullet.GetBulletText());
CPPUNIT_ASSERT_EQUAL(25, bullet.GetLeftIndent());
CPPUNIT_ASSERT_EQUAL(-5, bullet.GetLeftSubIndent());
}
void RichTextCtrlTestCase::FontSize()
{
m_rich->BeginFontSize(24);
m_rich->AddParagraph("Large text");
m_rich->EndFontSize();
wxTextAttr size;
m_rich->GetStyle(5, size);
CPPUNIT_ASSERT(size.HasFontSize());
CPPUNIT_ASSERT_EQUAL(24, size.GetFontSize());
}
void RichTextCtrlTestCase::Font()
{
wxFont font(14, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
m_rich->BeginFont(font);
m_rich->AddParagraph("paragraph with font");
m_rich->EndFont();
wxTextAttr fontstyle;
m_rich->GetStyle(5, fontstyle);
CPPUNIT_ASSERT_EQUAL(font, fontstyle.GetFont());
}
void RichTextCtrlTestCase::Delete()
{
m_rich->AddParagraph("here is a long long line in a paragraph");
m_rich->SetSelection(0, 6);
CPPUNIT_ASSERT(m_rich->CanDeleteSelection());
m_rich->DeleteSelection();
CPPUNIT_ASSERT_EQUAL("is a long long line in a paragraph", m_rich->GetValue());
m_rich->SetSelection(0, 5);
CPPUNIT_ASSERT(m_rich->CanDeleteSelection());
m_rich->DeleteSelectedContent();
CPPUNIT_ASSERT_EQUAL("long long line in a paragraph", m_rich->GetValue());
m_rich->Delete(wxRichTextRange(14, 29));
CPPUNIT_ASSERT_EQUAL("long long line", m_rich->GetValue());
}
void RichTextCtrlTestCase::Url()
{
m_rich->BeginURL("http://www.wxwidgets.org");
m_rich->WriteText("http://www.wxwidgets.org");
m_rich->EndURL();
wxTextAttr url;
m_rich->GetStyle(5, url);
CPPUNIT_ASSERT(url.HasURL());
CPPUNIT_ASSERT_EQUAL("http://www.wxwidgets.org", url.GetURL());
}
// Helper function for ::Table()
wxRichTextTable* GetCurrentTableInstance(wxRichTextParagraph* para)
{
wxRichTextTable* table = wxDynamicCast(para->FindObjectAtPosition(0), wxRichTextTable);
CPPUNIT_ASSERT(table);
return table;
}
void RichTextCtrlTestCase::Table()
{
m_rich->BeginSuppressUndo();
wxRichTextTable* table = m_rich->WriteTable(1, 1);
m_rich->EndSuppressUndo();
CPPUNIT_ASSERT(table);
CPPUNIT_ASSERT(m_rich->CanUndo() == false);
// Run the tests twice: first for the original table, then for a contained one
for (int t = 0; t < 2; ++t)
{
// Undo() and Redo() switch table instances, so invalidating 'table'
// The containing paragraph isn't altered, and so can be used to find the current object
wxRichTextParagraph* para = wxDynamicCast(table->GetParent(), wxRichTextParagraph);
CPPUNIT_ASSERT(para);
CPPUNIT_ASSERT(table->GetColumnCount() == 1);
CPPUNIT_ASSERT(table->GetRowCount() == 1);
// Test adding columns and rows
for (size_t n = 0; n < 3; ++n)
{
m_rich->BeginBatchUndo("Add col and row");
table->AddColumns(0, 1);
table->AddRows(0, 1);
m_rich->EndBatchUndo();
}
CPPUNIT_ASSERT(table->GetColumnCount() == 4);
CPPUNIT_ASSERT(table->GetRowCount() == 4);
// Test deleting columns and rows
for (size_t n = 0; n < 3; ++n)
{
m_rich->BeginBatchUndo("Delete col and row");
table->DeleteColumns(table->GetColumnCount() - 1, 1);
table->DeleteRows(table->GetRowCount() - 1, 1);
m_rich->EndBatchUndo();
}
CPPUNIT_ASSERT(table->GetColumnCount() == 1);
CPPUNIT_ASSERT(table->GetRowCount() == 1);
// Test undo, first of the deletions...
CPPUNIT_ASSERT(m_rich->CanUndo());
for (size_t n = 0; n < 3; ++n)
{
m_rich->Undo();
}
table = GetCurrentTableInstance(para);
CPPUNIT_ASSERT(table->GetColumnCount() == 4);
CPPUNIT_ASSERT(table->GetRowCount() == 4);
// ...then the additions
for (size_t n = 0; n < 3; ++n)
{
m_rich->Undo();
}
table = GetCurrentTableInstance(para);
CPPUNIT_ASSERT(table->GetColumnCount() == 1);
CPPUNIT_ASSERT(table->GetRowCount() == 1);
CPPUNIT_ASSERT(m_rich->CanUndo() == false);
// Similarly test redo. Additions:
CPPUNIT_ASSERT(m_rich->CanRedo());
for (size_t n = 0; n < 3; ++n)
{
m_rich->Redo();
}
table = GetCurrentTableInstance(para);
CPPUNIT_ASSERT(table->GetColumnCount() == 4);
CPPUNIT_ASSERT(table->GetRowCount() == 4);
// Deletions:
for (size_t n = 0; n < 3; ++n)
{
m_rich->Redo();
}
table = GetCurrentTableInstance(para);
CPPUNIT_ASSERT(table->GetColumnCount() == 1);
CPPUNIT_ASSERT(table->GetRowCount() == 1);
CPPUNIT_ASSERT(m_rich->CanRedo() == false);
// Now test multiple addition and deletion, and also suppression
m_rich->BeginSuppressUndo();
table->AddColumns(0, 3);
table->AddRows(0, 3);
CPPUNIT_ASSERT(table->GetColumnCount() == 4);
CPPUNIT_ASSERT(table->GetRowCount() == 4);
// Only delete 2 of these. This makes it easy to be sure we're dealing with the child table when we loop
table->DeleteColumns(0, 2);
table->DeleteRows(0, 2);
CPPUNIT_ASSERT(table->GetColumnCount() == 2);
CPPUNIT_ASSERT(table->GetRowCount() == 2);
m_rich->EndSuppressUndo();
m_rich->GetCommandProcessor()->ClearCommands(); // otherwise the command-history from this loop will cause CPPUNIT_ASSERT failures in the next one
if (t == 0)
{
// For round 2, re-run the tests on another table inside the last cell of the first one
wxRichTextCell* cell = table->GetCell(table->GetRowCount() - 1, table->GetColumnCount() - 1);
CPPUNIT_ASSERT(cell);
m_rich->SetFocusObject(cell);
m_rich->BeginSuppressUndo();
table = m_rich->WriteTable(1, 1);
m_rich->EndSuppressUndo();
CPPUNIT_ASSERT(table);
}
}
// Test ClearTable()
table->ClearTable();
CPPUNIT_ASSERT_EQUAL(0, table->GetCells().GetCount());
CPPUNIT_ASSERT_EQUAL(0, table->GetColumnCount());
CPPUNIT_ASSERT_EQUAL(0, table->GetRowCount());
m_rich->Clear();
m_rich->SetFocusObject(nullptr);
}
#endif //wxUSE_RICHTEXT

View File

@@ -0,0 +1,125 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/searchctrltest.cpp
// Purpose: wxSearchCtrl unit test
// Author: Vadim Zeitlin
// Created: 2013-01-20
// Copyright: (c) 2013 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_SEARCHCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/srchctrl.h"
#include "testwindow.h"
class SearchCtrlTestCase
{
public:
SearchCtrlTestCase()
: m_search(new wxSearchCtrl(wxTheApp->GetTopWindow(), wxID_ANY))
{
}
~SearchCtrlTestCase()
{
delete m_search;
}
void CheckStringSelection(const char *sel)
{
wxTextEntry * const entry = m_search;
CHECK( sel == entry->GetStringSelection() );
}
void AssertSelection(int from, int to, const char *sel)
{
wxTextEntry * const entry = m_search;
CHECK( entry->HasSelection() );
long fromReal,
toReal;
entry->GetSelection(&fromReal, &toReal);
CHECK( from == fromReal );
CHECK( to == toReal );
CHECK( from == entry->GetInsertionPoint() );
CheckStringSelection(sel);
}
protected:
wxSearchCtrl* const m_search;
};
#define SEARCH_CTRL_TEST_CASE(name, tags) \
TEST_CASE_METHOD(SearchCtrlTestCase, name, tags)
// TODO OS X test only passes when run solo ...
#ifndef __WXOSX__
SEARCH_CTRL_TEST_CASE("wxSearchCtrl::Focus", "[wxSearchCtrl][focus]")
{
m_search->SetFocus();
CHECK_FOCUS_IS( m_search );
}
#endif // !__WXOSX__
SEARCH_CTRL_TEST_CASE("wxSearchCtrl::ChangeValue", "[wxSearchCtrl][text]")
{
CHECK( m_search->GetValue() == wxString() );
m_search->ChangeValue("foo");
CHECK( m_search->GetValue() == "foo" );
m_search->Clear();
CHECK( m_search->GetValue() == "" );
}
SEARCH_CTRL_TEST_CASE("wxSearchCtrl::SetValue", "[wxSearchCtrl][set_value]")
{
// Work around bug with hint implementation in wxGTK2.
#if defined(__WXGTK__) && !defined(__WXGTK3__)
m_search->Clear();
#endif
CHECK( m_search->IsEmpty() );
m_search->SetValue("foo");
CHECK( m_search->GetValue() == "foo" );
m_search->SetValue("");
CHECK( m_search->IsEmpty() );
m_search->SetValue("hi");
CHECK( "hi" == m_search->GetValue() );
m_search->SetValue("bye");
CHECK( "bye" == m_search->GetValue() );
}
SEARCH_CTRL_TEST_CASE("wxSearchCtrl::Selection", "[wxSearchCtrl][selection]")
{
wxTextEntry * const entry = m_search;
entry->SetValue("0123456789");
entry->SetSelection(2, 4);
AssertSelection(2, 4, "23"); // not "234"!
entry->SetSelection(3, -1);
AssertSelection(3, 10, "3456789");
entry->SelectAll();
AssertSelection(0, 10, "0123456789");
entry->SetSelection(0, 0);
CHECK( !entry->HasSelection() );
}
#endif // wxUSE_SEARCHCTRL

View File

@@ -0,0 +1,66 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/simplebooktest.cpp
// Purpose: wxSimplebook unit test
// Author: Vadim Zeitlin
// Created: 2013-06-23
// Copyright: (c) 2013 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_BOOKCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/simplebook.h"
#include "bookctrlbasetest.h"
class SimplebookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase
{
public:
SimplebookTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxBookCtrlBase *GetBase() const override { return m_simplebook; }
virtual wxEventType GetChangedEvent() const override
{ return wxEVT_BOOKCTRL_PAGE_CHANGED; }
virtual wxEventType GetChangingEvent() const override
{ return wxEVT_BOOKCTRL_PAGE_CHANGING; }
CPPUNIT_TEST_SUITE( SimplebookTestCase );
wxBOOK_CTRL_BASE_TESTS();
CPPUNIT_TEST_SUITE_END();
wxSimplebook *m_simplebook;
wxDECLARE_NO_COPY_CLASS(SimplebookTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( SimplebookTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SimplebookTestCase, "SimplebookTestCase" );
void SimplebookTestCase::setUp()
{
m_simplebook = new wxSimplebook(wxTheApp->GetTopWindow(), wxID_ANY);
AddPanels();
}
void SimplebookTestCase::tearDown()
{
wxDELETE(m_simplebook);
}
#endif // wxUSE_BOOKCTRL

View File

@@ -0,0 +1,234 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/slidertest.cpp
// Purpose: wxSlider unit test
// Author: Steven Lamerton
// Created: 2010-07-20
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_SLIDER
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/slider.h"
#endif // WX_PRECOMP
#include "wx/uiaction.h"
#include "testableframe.h"
class SliderTestCase : public CppUnit::TestCase
{
public:
SliderTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( SliderTestCase );
#ifndef __WXOSX__
WXUISIM_TEST( PageUpDown );
WXUISIM_TEST( LineUpDown );
WXUISIM_TEST( EvtSlider );
WXUISIM_TEST( LinePageSize );
#endif
CPPUNIT_TEST( Value );
CPPUNIT_TEST( Range );
WXUISIM_TEST( Thumb );
CPPUNIT_TEST( PseudoTest_Inversed );
CPPUNIT_TEST( Value );
CPPUNIT_TEST( Range );
CPPUNIT_TEST_SUITE_END();
void PageUpDown();
void LineUpDown();
void EvtSlider();
void LinePageSize();
void Value();
void Range();
void Thumb();
void PseudoTest_Inversed() { ms_inversed = true; }
static bool ms_inversed;
wxSlider* m_slider;
wxDECLARE_NO_COPY_CLASS(SliderTestCase);
};
bool SliderTestCase::ms_inversed = false;
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( SliderTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( SliderTestCase, "SliderTestCase" );
void SliderTestCase::setUp()
{
long style = wxSL_HORIZONTAL;
if ( ms_inversed )
style |= wxSL_INVERSE;
m_slider = new wxSlider(wxTheApp->GetTopWindow(), wxID_ANY, 50, 0, 100,
wxDefaultPosition, wxDefaultSize,
style);
}
void SliderTestCase::tearDown()
{
wxDELETE(m_slider);
}
void SliderTestCase::PageUpDown()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter pageup(m_slider, wxEVT_SCROLL_PAGEUP);
EventCounter pagedown(m_slider, wxEVT_SCROLL_PAGEDOWN);
wxUIActionSimulator sim;
m_slider->SetFocus();
wxYield();
sim.Char(WXK_PAGEUP);
sim.Char(WXK_PAGEDOWN);
wxYield();
CPPUNIT_ASSERT_EQUAL(1, pageup.GetCount());
CPPUNIT_ASSERT_EQUAL(1, pagedown.GetCount());
#endif
}
void SliderTestCase::LineUpDown()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter lineup(m_slider, wxEVT_SCROLL_LINEUP);
EventCounter linedown(m_slider, wxEVT_SCROLL_LINEDOWN);
wxUIActionSimulator sim;
m_slider->SetFocus();
wxYield();
sim.Char(WXK_UP);
sim.Char(WXK_DOWN);
wxYield();
CPPUNIT_ASSERT_EQUAL(1, lineup.GetCount());
CPPUNIT_ASSERT_EQUAL(1, linedown.GetCount());
#endif
}
void SliderTestCase::EvtSlider()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter slider(m_slider, wxEVT_SLIDER);
wxUIActionSimulator sim;
m_slider->SetFocus();
wxYield();
sim.Char(WXK_UP);
sim.Char(WXK_DOWN);
wxYield();
CPPUNIT_ASSERT_EQUAL(2, slider.GetCount());
#endif
}
void SliderTestCase::LinePageSize()
{
#if wxUSE_UIACTIONSIMULATOR
wxUIActionSimulator sim;
m_slider->SetFocus();
wxYield();
m_slider->SetPageSize(20);
sim.Char(WXK_PAGEUP);
wxYield();
CPPUNIT_ASSERT_EQUAL(20, m_slider->GetPageSize());
CPPUNIT_ASSERT_EQUAL(30, m_slider->GetValue());
m_slider->SetLineSize(2);
sim.Char(WXK_UP);
wxYield();
CPPUNIT_ASSERT_EQUAL(2, m_slider->GetLineSize());
CPPUNIT_ASSERT_EQUAL(28, m_slider->GetValue());
#endif
}
void SliderTestCase::Value()
{
m_slider->SetValue(30);
CPPUNIT_ASSERT_EQUAL(30, m_slider->GetValue());
//When setting a value larger that max or smaller than min
//max and min are set
m_slider->SetValue(-1);
CPPUNIT_ASSERT_EQUAL(0, m_slider->GetValue());
m_slider->SetValue(110);
CPPUNIT_ASSERT_EQUAL(100, m_slider->GetValue());
}
void SliderTestCase::Range()
{
CPPUNIT_ASSERT_EQUAL(0, m_slider->GetMin());
CPPUNIT_ASSERT_EQUAL(100, m_slider->GetMax());
// Changing range shouldn't change the value.
m_slider->SetValue(17);
m_slider->SetRange(0, 200);
CPPUNIT_ASSERT_EQUAL(17, m_slider->GetValue());
//Test negative ranges
m_slider->SetRange(-50, 0);
CPPUNIT_ASSERT_EQUAL(-50, m_slider->GetMin());
CPPUNIT_ASSERT_EQUAL(0, m_slider->GetMax());
}
void SliderTestCase::Thumb()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter track(m_slider, wxEVT_SCROLL_THUMBTRACK);
EventCounter release(m_slider, wxEVT_SCROLL_THUMBRELEASE);
EventCounter changed(m_slider, wxEVT_SCROLL_CHANGED);
wxUIActionSimulator sim;
m_slider->SetValue(0);
// use the slider real position for dragging the mouse.
const int ypos = m_slider->GetSize().y / 2;
sim.MouseDragDrop(m_slider->ClientToScreen(wxPoint(10, ypos)),m_slider->ClientToScreen(wxPoint(50, ypos)));
wxYield();
CPPUNIT_ASSERT(track.GetCount() != 0);
CPPUNIT_ASSERT_EQUAL(1, release.GetCount());
#if defined(__WXMSW__) || defined(__WXGTK__) || defined(__WXQT__)
CPPUNIT_ASSERT_EQUAL(1, changed.GetCount());
#endif
#endif
}
#endif

View File

@@ -0,0 +1,295 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/spinctrldbltest.cpp
// Purpose: wxSpinCtrlDouble unit test
// Author: Steven Lamerton
// Created: 2010-07-22
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_SPINCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "testableframe.h"
#include "wx/uiaction.h"
#include "wx/spinctrl.h"
#include <memory>
class SpinCtrlDoubleTestCase
{
public:
SpinCtrlDoubleTestCase(int style = wxSP_ARROW_KEYS)
: m_spin(new wxSpinCtrlDouble(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
style))
{
}
~SpinCtrlDoubleTestCase()
{
delete m_spin;
}
protected:
wxSpinCtrlDouble* const m_spin;
wxDECLARE_NO_COPY_CLASS(SpinCtrlDoubleTestCase);
};
class SpinCtrlDoubleTestCaseWrap : public SpinCtrlDoubleTestCase
{
public:
SpinCtrlDoubleTestCaseWrap()
: SpinCtrlDoubleTestCase(wxSP_ARROW_KEYS | wxSP_WRAP)
{
}
};
TEST_CASE("SpinCtrlDouble::NoEventsInCtor", "[spinctrl][spinctrldouble]")
{
// Verify that creating the control does not generate any events. This is
// unexpected and shouldn't happen.
std::unique_ptr<wxSpinCtrlDouble> m_spin(new wxSpinCtrlDouble);
EventCounter updatedSpin(m_spin.get(), wxEVT_SPINCTRLDOUBLE);
EventCounter updatedText(m_spin.get(), wxEVT_TEXT);
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0,
0., 100., 17.);
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Arrows", "[spinctrl][spinctrldouble]")
{
EventCounter updated(m_spin, wxEVT_SPINCTRLDOUBLE);
wxUIActionSimulator sim;
m_spin->SetFocus();
wxYield();
sim.Char(WXK_UP);
wxYield();
CHECK( updated.GetCount() == 1 );
CHECK( m_spin->GetValue() == 1.0 );
updated.Clear();
sim.Char(WXK_DOWN);
wxYield();
CHECK( updated.GetCount() == 1 );
CHECK( m_spin->GetValue() == 0.0 );
}
TEST_CASE_METHOD(SpinCtrlDoubleTestCaseWrap,
"SpinCtrlDouble::Wrap", "[spinctrl][spinctrldouble]")
{
wxUIActionSimulator sim;
m_spin->SetFocus();
wxYield();
sim.Char(WXK_DOWN);
wxYield();
CHECK( m_spin->GetValue() == 100.0 );
sim.Char(WXK_UP);
wxYield();
CHECK( m_spin->GetValue() == 0.0 );
}
#endif // wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Range", "[spinctrl][spinctrldouble]")
{
CHECK( m_spin->GetMin() == 0.0 );
CHECK( m_spin->GetMax() == 100.0 );
// Test that the value is adjusted to be inside the new valid range but
// that this doesn't result in any events (as this is not something done by
// the user).
{
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRLDOUBLE);
EventCounter updatedText(m_spin, wxEVT_TEXT);
m_spin->SetRange(1., 10.);
CHECK( m_spin->GetValue() == 1. );
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
}
//Test negative ranges
m_spin->SetRange(-10.0, 10.0);
CHECK( m_spin->GetMin() == -10.0 );
CHECK( m_spin->GetMax() == 10.0 );
#ifndef __WXQT__
//Test backwards ranges
m_spin->SetRange(75.0, 50.0);
CHECK( m_spin->GetMin() == 75.0 );
CHECK( m_spin->GetMax() == 50.0 );
#endif
}
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Value", "[spinctrl][spinctrldouble]")
{
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRLDOUBLE);
EventCounter updatedText(m_spin, wxEVT_TEXT);
m_spin->SetDigits(2);
m_spin->SetIncrement(0.1);
CHECK( m_spin->GetValue() == 0.0 );
m_spin->SetValue(50.0);
CHECK( m_spin->GetValue() == 50.0 );
m_spin->SetValue(49.1);
CHECK( m_spin->GetValue() == 49.1 );
// Calling SetValue() shouldn't have generated any events.
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
// Also test that setting the text value works.
CHECK( m_spin->GetTextValue() == "49.10" );
m_spin->SetValue("57.30");
CHECK( m_spin->GetTextValue() == "57.30" );
CHECK( m_spin->GetValue() == 57.3 );
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
m_spin->SetValue("");
#ifndef __WXQT__
CHECK( m_spin->GetTextValue() == "" );
#else
CHECK( m_spin->GetTextValue() == "0.00" ); // the control automatically displays minVal
#endif
CHECK( m_spin->GetValue() == 0 );
CHECK( updatedSpin.GetCount() == 0 );
CHECK( updatedText.GetCount() == 0 );
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Increment", "[spinctrl][spinctrldouble]")
{
CHECK( m_spin->GetIncrement() == 1.0 );
m_spin->SetDigits(1);
m_spin->SetIncrement(0.1);
CHECK( m_spin->GetIncrement() == 0.1 );
wxUIActionSimulator sim;
m_spin->SetFocus();
wxYield();
sim.Char(WXK_UP);
wxYield();
CHECK( m_spin->GetValue() == 0.1 );
}
#endif // wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(SpinCtrlDoubleTestCase,
"SpinCtrlDouble::Digits", "[spinctrl][spinctrldouble]")
{
// Setting increment should adjust the number of digits shown to be big
// enough to show numbers with the corresponding granularity.
m_spin->SetIncrement(0.1);
m_spin->SetValue(1.23456789);
CHECK( m_spin->GetTextValue() == "1.2" );
m_spin->SetIncrement(0.01);
m_spin->SetValue(1.23456789);
CHECK( m_spin->GetTextValue() == "1.23" );
m_spin->SetDigits(5);
CHECK( m_spin->GetDigits() == 5 );
m_spin->SetValue(1.23456789);
CHECK( m_spin->GetTextValue() == "1.23457" );
// The number of digits shouldn't (implicitly) decrease however.
m_spin->SetIncrement(0.001);
m_spin->SetValue(1.23456789);
CHECK( m_spin->GetTextValue() == "1.23457" );
// Check that using increment greater than 1 also works.
m_spin->SetDigits(0);
m_spin->SetIncrement(2.5);
m_spin->SetValue(7.5);
CHECK( m_spin->GetTextValue() == "7.5" );
}
static inline unsigned int GetInitialDigits(double inc)
{
std::unique_ptr<wxSpinCtrlDouble> sc(new wxSpinCtrlDouble
(
wxTheApp->GetTopWindow(),
wxID_ANY,
wxEmptyString,
wxDefaultPosition,
wxDefaultSize,
wxSP_ARROW_KEYS,
0, 50, 0,
inc
));
return sc->GetDigits();
}
TEST_CASE("SpinCtrlDouble::InitialDigits", "[spinctrldouble][initialdigits]")
{
REQUIRE(GetInitialDigits(15) == 0);
REQUIRE(GetInitialDigits(10) == 0);
REQUIRE(GetInitialDigits(1) == 0);
REQUIRE(GetInitialDigits(0.999) == 1);
REQUIRE(GetInitialDigits(0.15) == 1);
REQUIRE(GetInitialDigits(0.11) == 1);
REQUIRE(GetInitialDigits(0.1) == 1);
REQUIRE(GetInitialDigits(0.0999) == 2);
REQUIRE(GetInitialDigits(0.015) == 2);
REQUIRE(GetInitialDigits(0.011) == 2);
REQUIRE(GetInitialDigits(0.01) == 2);
REQUIRE(GetInitialDigits(9.99e-5) == 5);
REQUIRE(GetInitialDigits(1e-5) == 5);
REQUIRE(GetInitialDigits(9.9999e-10) == 10);
REQUIRE(GetInitialDigits(1e-10) == 10);
REQUIRE(GetInitialDigits(9.9999e-20) == 20);
REQUIRE(GetInitialDigits(1e-20) == 20);
REQUIRE(GetInitialDigits(9.9999e-21) == 20);
REQUIRE(GetInitialDigits(1e-21) == 20);
REQUIRE(GetInitialDigits(9.9999e-22) == 20);
REQUIRE(GetInitialDigits(1e-22) == 20);
}
#endif

View File

@@ -0,0 +1,403 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/spinctrltest.cpp
// Purpose: wxSpinCtrl unit test
// Author: Steven Lamerton
// Created: 2010-07-21
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_SPINCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "testableframe.h"
#include "wx/uiaction.h"
#include "wx/spinctrl.h"
#include "wx/textctrl.h"
class SpinCtrlTestCase1
{
public:
SpinCtrlTestCase1()
: m_spin(new wxSpinCtrl())
{
}
~SpinCtrlTestCase1()
{
delete m_spin;
}
protected:
wxSpinCtrl* m_spin;
};
class SpinCtrlTestCase2
{
public:
SpinCtrlTestCase2()
: m_spin(new wxSpinCtrl(wxTheApp->GetTopWindow()))
{
}
~SpinCtrlTestCase2()
{
delete m_spin;
}
protected:
wxSpinCtrl* m_spin;
};
class SpinCtrlTestCase3
{
public:
SpinCtrlTestCase3()
: m_spin(new wxSpinCtrl(wxTheApp->GetTopWindow()))
{
m_spin->Bind(wxEVT_SPINCTRL, &SpinCtrlTestCase3::OnSpinSetValue, this);
}
~SpinCtrlTestCase3()
{
delete m_spin;
}
private:
void OnSpinSetValue(wxSpinEvent &e)
{
// Constrain the value to be in the 1..16 range or 32.
int newVal = e.GetValue();
if ( newVal == 31 )
m_spin->SetValue(16);
else if ( newVal > 16 )
m_spin->SetValue(32);
}
protected:
wxSpinCtrl* m_spin;
};
TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Init", "[spinctrl]")
{
// Initial value is defined by "initial" argument which is 0 by default.
CHECK(m_spin->GetValue() == 0);
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::Init2", "[spinctrl]")
{
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0,
0, 100, 17);
// Recreate the control with another "initial" to check this.
CHECK(m_spin->GetValue() == 17);
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::Init3", "[spinctrl]")
{
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0,
0, 200, 150);
// Recreate the control with another "initial" outside of standard spin
// ctrl range.
CHECK(m_spin->GetValue() == 150);
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::Init4", "[spinctrl]")
{
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "99",
wxDefaultPosition, wxDefaultSize, 0,
0, 100, 17);
// Recreate the control with another "initial" outside of standard spin
// ctrl range.
// But if the text string is specified, it takes precedence.
CHECK(m_spin->GetValue() == 99);
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::InitOutOfRange", "[spinctrl]")
{
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0,
10, 20, 0);
// Recreate the control with another "initial" outside of the valid range:
// it shouldn't be taken into account.
CHECK(m_spin->GetValue() == 10);
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::NoEventsInCtor", "[spinctrl]")
{
// Verify that creating the control does not generate any events. This is
// unexpected and shouldn't happen.
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRL);
EventCounter updatedText(m_spin, wxEVT_TEXT);
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize, 0,
0, 100, 17);
CHECK(updatedSpin.GetCount() == 0);
CHECK(updatedText.GetCount() == 0);
}
TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Arrows", "[spinctrl]")
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter updated(m_spin, wxEVT_SPINCTRL);
wxUIActionSimulator sim;
m_spin->SetFocus();
wxYield();
sim.Char(WXK_UP);
wxYield();
CHECK(updated.GetCount() == 1);
CHECK(m_spin->GetValue() == 1);
updated.Clear();
sim.Char(WXK_DOWN);
wxYield();
CHECK(updated.GetCount() == 1);
CHECK(m_spin->GetValue() == 0);
#endif
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::Wrap", "[spinctrl]")
{
#if wxUSE_UIACTIONSIMULATOR
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
wxSP_ARROW_KEYS | wxSP_WRAP);
wxUIActionSimulator sim;
m_spin->SetFocus();
wxYield();
sim.Char(WXK_DOWN);
wxYield();
CHECK(m_spin->GetValue() == 100);
sim.Char(WXK_UP);
wxYield();
CHECK(m_spin->GetValue() == 0);
#endif
}
TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Range", "[spinctrl]")
{
CHECK(m_spin->GetMin() == 0);
CHECK(m_spin->GetMax() == 100);
CHECK(m_spin->GetBase() == 10);
// Test that the value is adjusted to be inside the new valid range but
// that this doesn't result in any events (as this is not something done by
// the user).
{
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRL);
EventCounter updatedText(m_spin, wxEVT_TEXT);
m_spin->SetRange(1, 10);
CHECK(m_spin->GetValue() == 1);
CHECK(updatedSpin.GetCount() == 0);
CHECK(updatedText.GetCount() == 0);
}
// Test negative ranges
m_spin->SetRange(-10, 10);
CHECK(m_spin->GetMin() == -10);
CHECK(m_spin->GetMax() == 10);
// With base 16 only ranges including values >= 0 are allowed
m_spin->SetRange(0, 10);
int oldMinVal = m_spin->GetMin();
int oldMaxVal = m_spin->GetMax();
CHECK(oldMinVal == 0);
CHECK(oldMaxVal == 10);
CHECK(m_spin->SetBase(16) == true);
CHECK(m_spin->GetBase() == 16);
// New range should be silently ignored
m_spin->SetRange(-20, 20);
CHECK(m_spin->GetMin() == oldMinVal);
CHECK(m_spin->GetMax() == oldMaxVal);
// This range should be accepted
m_spin->SetRange(2, 8);
CHECK(m_spin->GetMin() == 2);
CHECK(m_spin->GetMax() == 8);
CHECK(m_spin->SetBase(10) == true);
CHECK(m_spin->GetBase() == 10);
#ifndef __WXQT__
//Test backwards ranges
m_spin->SetRange(75, 50);
CHECK(m_spin->GetMin() == 75);
CHECK(m_spin->GetMax() == 50);
#endif
}
TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Value", "[spinctrl]")
{
EventCounter updatedSpin(m_spin, wxEVT_SPINCTRL);
EventCounter updatedText(m_spin, wxEVT_TEXT);
CHECK(m_spin->GetValue() == 0);
m_spin->SetValue(50);
CHECK(m_spin->GetValue() == 50);
m_spin->SetValue(-10);
CHECK(m_spin->GetValue() == 0);
m_spin->SetValue(110);
CHECK(m_spin->GetValue() == 100);
// Calling SetValue() shouldn't have generated any events.
CHECK(updatedSpin.GetCount() == 0);
CHECK(updatedText.GetCount() == 0);
// Also test that setting the text value works.
CHECK( m_spin->GetTextValue() == "100" );
m_spin->SetValue("57");
CHECK( m_spin->GetTextValue() == "57" );
CHECK( m_spin->GetValue() == 57 );
CHECK(updatedSpin.GetCount() == 0);
CHECK(updatedText.GetCount() == 0);
m_spin->SetValue("");
#ifndef __WXQT__
CHECK( m_spin->GetTextValue() == "" );
#else
CHECK( m_spin->GetTextValue() == "0" ); // the control automatically displays minVal
#endif
CHECK( m_spin->GetValue() == 0 );
CHECK(updatedSpin.GetCount() == 0);
CHECK(updatedText.GetCount() == 0);
}
TEST_CASE_METHOD(SpinCtrlTestCase2, "SpinCtrl::Base", "[spinctrl]")
{
CHECK(m_spin->GetMin() == 0);
CHECK(m_spin->GetMax() == 100);
CHECK(m_spin->GetBase() == 10);
// Only 10 and 16 bases are allowed
CHECK(m_spin->SetBase(10) == true);
CHECK(m_spin->GetBase() == 10);
CHECK_FALSE(m_spin->SetBase(8));
CHECK(m_spin->GetBase() == 10);
CHECK_FALSE(m_spin->SetBase(2));
CHECK(m_spin->GetBase() == 10);
CHECK(m_spin->SetBase(16) == true);
CHECK(m_spin->GetBase() == 16);
CHECK(m_spin->SetBase(10) == true);
CHECK(m_spin->GetBase() == 10);
// When range contains negative values only base 10 is allowed
m_spin->SetRange(-10, 10);
CHECK(m_spin->GetMin() == -10);
CHECK(m_spin->GetMax() == 10);
CHECK_FALSE(m_spin->SetBase(8));
CHECK(m_spin->GetBase() == 10);
CHECK_FALSE(m_spin->SetBase(2));
CHECK(m_spin->GetBase() == 10);
CHECK_FALSE(m_spin->SetBase(16));
CHECK(m_spin->GetBase() == 10);
CHECK(m_spin->SetBase(10) == true);
CHECK(m_spin->GetBase() == 10);
}
TEST_CASE_METHOD(SpinCtrlTestCase3, "SpinCtrl::SetValueInsideEventHandler", "[spinctrl]")
{
#if wxUSE_UIACTIONSIMULATOR
// A dummy control with which we change the focus.
wxTextCtrl* text = new wxTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY);
text->Move(m_spin->GetSize().x, m_spin->GetSize().y * 3);
wxUIActionSimulator sim;
// run multiple times to make sure there are no issues with keeping old value
for ( size_t i = 0; i < 2; i++ )
{
m_spin->SetFocus();
wxYield();
sim.Char(WXK_DELETE);
sim.Char(WXK_DELETE);
sim.Text("20");
wxYield();
text->SetFocus();
wxYield();
CHECK(m_spin->GetValue() == 32);
}
delete text;
#endif // wxUSE_UIACTIONSIMULATOR
}
TEST_CASE_METHOD(SpinCtrlTestCase1, "SpinCtrl::Increment", "[spinctrl]")
{
#if wxUSE_UIACTIONSIMULATOR
m_spin->Create(wxTheApp->GetTopWindow(), wxID_ANY, "",
wxDefaultPosition, wxDefaultSize,
wxSP_ARROW_KEYS | wxSP_WRAP);
wxUIActionSimulator sim;
CHECK( m_spin->GetIncrement() == 1 );
m_spin->SetFocus();
wxYield();
m_spin->SetIncrement( 5 );
sim.Char(WXK_UP);
wxYield();
CHECK(m_spin->GetValue() == 5);
int increment = m_spin->GetIncrement();
CHECK( increment == 5 );
#endif
}
#endif

View File

@@ -0,0 +1,165 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/styledtextctrltest.cpp
// Purpose: wxStyledTextCtrl unit test
// Author: New Pagodi
// Created: 2019-03-10
// Copyright: (c) 2019 wxWidgets development team
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_STC
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/stc/stc.h"
#include "wx/uiaction.h"
#include "testwindow.h"
#if defined(__WXOSX_COCOA__) || defined(__WXMSW__) || defined(__WXGTK__)
class StcPopupWindowsTestCase
{
public:
StcPopupWindowsTestCase()
: m_stc(new wxStyledTextCtrl(wxTheApp->GetTopWindow(), wxID_ANY))
{
m_focusAlwaysRetained=true;
m_calltipClickReceived=false;
m_stc->Bind(wxEVT_KILL_FOCUS,
&StcPopupWindowsTestCase::OnKillSTCFocus, this);
m_stc->Bind(wxEVT_STC_CALLTIP_CLICK,
&StcPopupWindowsTestCase::OnCallTipClick, this);
}
~StcPopupWindowsTestCase()
{
delete m_stc;
}
void OnKillSTCFocus(wxFocusEvent& WXUNUSED(event))
{
m_focusAlwaysRetained=false;
}
void OnCallTipClick(wxStyledTextEvent& WXUNUSED(event))
{
m_calltipClickReceived=true;
}
protected:
wxStyledTextCtrl* const m_stc;
bool m_focusAlwaysRetained;
bool m_calltipClickReceived;
};
// This set of tests is used to verify that an autocompletion popup does not
// take focus from its parent styled text control.
TEST_CASE_METHOD(StcPopupWindowsTestCase,
"wxStyledTextCtrl::AutoComp",
"[wxStyledTextCtrl][focus]")
{
m_stc->SetFocus();
m_focusAlwaysRetained = true;
m_stc->AutoCompShow(0,"ability able about above abroad absence absent");
#if wxUSE_UIACTIONSIMULATOR
// Pressing the tab key should cause the current entry in the list to be
// entered into the styled text control. However with GTK+, characters sent
// with the UI simulator seem to arrive too late, so select the current
// entry with a double click instead.
wxUIActionSimulator sim;
#ifdef __WXGTK__
wxPoint zeroPosition = m_stc->PointFromPosition(0);
int textHt = m_stc->TextHeight(0);
int textWd = m_stc->TextWidth(0,"ability");
wxPoint autoCompPoint(zeroPosition.x + textWd/2,
zeroPosition.y + textHt + textHt/2);
wxPoint scrnPoint = m_stc->ClientToScreen(autoCompPoint);
sim.MouseMove(scrnPoint);
sim.MouseDblClick();
#else
sim.Char(WXK_TAB);
#endif // __WXGTK__
::wxYield();
CHECK( m_stc->GetText() == "ability" );
#endif //wxUSE_UIACTIONSIMULATOR
if ( m_stc->AutoCompActive() )
m_stc->AutoCompCancel();
CHECK_FOCUS_IS( m_stc );
// Unfortunately under GTK we do get focus loss events, at least sometimes
// (and actually more often than not, especially with GTK2, but this
// happens with GTK3 too).
#ifndef __WXGTK__
CHECK( m_focusAlwaysRetained );
#endif // !__WXGTK__
}
// This test is used to verify that a call tip receives mouse clicks. However
// the clicks do sent with the UI simulator do not seem to be received on
// cocoa for some reason, so skip the test there for now.
#if !defined(__WXOSX_COCOA__)
TEST_CASE_METHOD(StcPopupWindowsTestCase,
"wxStyledTextCtrl::Calltip",
"[wxStyledTextCtrl][focus]")
{
m_stc->SetFocus();
m_calltipClickReceived = false;
m_focusAlwaysRetained = true;
wxString calltipText = "This is a calltip.";
m_stc->CallTipShow(0,calltipText);
#if wxUSE_UIACTIONSIMULATOR
wxUIActionSimulator sim;
wxPoint zeroPosition = m_stc->PointFromPosition(0);
int textHt = m_stc->TextHeight(0);
int textWd = m_stc->TextWidth(0,calltipText);
// zeroPosition is the top left of position 0 and the call tip should have
// roughly the same height as textHt (there seems to be some extra padding
// that makes it a little taller, but it's roughly the same height),
// so (zeroPosition.x+textWd/2,zeroPosition.y+textHt+textHt/2) should
// be the middle of the calltip.
wxPoint calltipMidPoint(zeroPosition.x + textWd/2,
zeroPosition.y + textHt + textHt/2);
wxPoint scrnPoint = m_stc->ClientToScreen(calltipMidPoint);
sim.MouseMove(scrnPoint);
sim.MouseClick();
::wxYield();
CHECK( m_calltipClickReceived );
#endif // wxUSE_UIACTIONSIMULATOR
if ( m_stc->CallTipActive() )
m_stc->CallTipCancel();
// Verify that clicking the call tip did not take focus from the STC.
//
// Unfortunately this test fails for unknown reasons under Xvfb (but only
// there).
if ( !IsRunningUnderXVFB() )
CHECK_FOCUS_IS( m_stc );
// With wxGTK there is the same problem here as in the test above.
#ifndef __WXGTK__
CHECK( m_focusAlwaysRetained );
#endif // !__WXGTK__
}
#endif // !defined(__WXOSX_COCOA__)
#endif // defined(__WXOSX_COCOA__) || defined(__WXMSW__) || defined(__WXGTK__)
#endif // wxUSE_STC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,570 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/textentrytest.cpp
// Purpose: TestEntryTestCase implementation
// Author: Vadim Zeitlin
// Created: 2008-09-19 (extracted from textctrltest.cpp)
// Copyright: (c) 2007, 2008 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/dialog.h"
#include "wx/event.h"
#include "wx/sizer.h"
#include "wx/textctrl.h"
#include "wx/textentry.h"
#include "wx/timer.h"
#include "wx/window.h"
#endif // WX_PRECOMP
#include "textentrytest.h"
#include "testableframe.h"
#include "wx/uiaction.h"
#include <memory>
void TextEntryTestCase::SetValue()
{
wxTextEntry * const entry = GetTestEntry();
CPPUNIT_ASSERT( entry->IsEmpty() );
entry->SetValue("foo");
CPPUNIT_ASSERT_EQUAL( "foo", entry->GetValue() );
entry->SetValue("");
CPPUNIT_ASSERT( entry->IsEmpty() );
entry->SetValue("hi");
CPPUNIT_ASSERT_EQUAL( "hi", entry->GetValue() );
entry->SetValue("bye");
CPPUNIT_ASSERT_EQUAL( "bye", entry->GetValue() );
}
void TextEntryTestCase::TextChangeEvents()
{
EventCounter updated(GetTestWindow(), wxEVT_TEXT);
wxTextEntry * const entry = GetTestEntry();
// notice that SetValue() generates an event even if the text didn't change
entry->SetValue("");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->SetValue("foo");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->SetValue("foo");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->SetValue("");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->ChangeValue("bar");
CPPUNIT_ASSERT_EQUAL( 0, updated.GetCount() );
entry->AppendText("bar");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->Replace(3, 6, "baz");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->Remove(0, 3);
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->WriteText("foo");
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->Clear();
CPPUNIT_ASSERT_EQUAL( 1, updated.GetCount() );
updated.Clear();
entry->ChangeValue("");
CPPUNIT_ASSERT_EQUAL( 0, updated.GetCount() );
updated.Clear();
entry->ChangeValue("non-empty");
CPPUNIT_ASSERT_EQUAL( 0, updated.GetCount() );
updated.Clear();
entry->ChangeValue("");
CPPUNIT_ASSERT_EQUAL( 0, updated.GetCount() );
updated.Clear();
}
void TextEntryTestCase::CheckStringSelection(const char *sel)
{
CPPUNIT_ASSERT_EQUAL( sel, GetTestEntry()->GetStringSelection() );
}
void TextEntryTestCase::AssertSelection(int from, int to, const char *sel)
{
wxTextEntry * const entry = GetTestEntry();
CPPUNIT_ASSERT( entry->HasSelection() );
long fromReal,
toReal;
entry->GetSelection(&fromReal, &toReal);
CPPUNIT_ASSERT_EQUAL( from, fromReal );
CPPUNIT_ASSERT_EQUAL( to, toReal );
CPPUNIT_ASSERT_EQUAL( from, entry->GetInsertionPoint() );
CheckStringSelection(sel);
}
void TextEntryTestCase::Selection()
{
wxTextEntry * const entry = GetTestEntry();
entry->SetValue("0123456789");
entry->SetSelection(2, 4);
AssertSelection(2, 4, "23"); // not "234"!
entry->SetSelection(3, -1);
AssertSelection(3, 10, "3456789");
entry->SelectAll();
AssertSelection(0, 10, "0123456789");
entry->SetSelection(0, 0);
CPPUNIT_ASSERT( !entry->HasSelection() );
}
void TextEntryTestCase::InsertionPoint()
{
wxTextEntry * const entry = GetTestEntry();
CPPUNIT_ASSERT_EQUAL( 0, entry->GetLastPosition() );
CPPUNIT_ASSERT_EQUAL( 0, entry->GetInsertionPoint() );
entry->SetValue("0"); // should put the insertion point in front
CPPUNIT_ASSERT_EQUAL( 1, entry->GetLastPosition() );
CPPUNIT_ASSERT_EQUAL( 0, entry->GetInsertionPoint() );
entry->AppendText("12"); // should update the insertion point position
CPPUNIT_ASSERT_EQUAL( 3, entry->GetLastPosition() );
CPPUNIT_ASSERT_EQUAL( 3, entry->GetInsertionPoint() );
entry->SetInsertionPoint(1);
CPPUNIT_ASSERT_EQUAL( 3, entry->GetLastPosition() );
CPPUNIT_ASSERT_EQUAL( 1, entry->GetInsertionPoint() );
entry->SetValue("012"); // shouldn't change the position if no real change
CPPUNIT_ASSERT_EQUAL( 1, entry->GetInsertionPoint() );
entry->ChangeValue("012"); // same as for SetValue()
CPPUNIT_ASSERT_EQUAL( 1, entry->GetInsertionPoint() );
entry->SetInsertionPointEnd();
CPPUNIT_ASSERT_EQUAL( 3, entry->GetInsertionPoint() );
entry->SetInsertionPoint(0);
entry->WriteText("-"); // should move it after the written text
CPPUNIT_ASSERT_EQUAL( 4, entry->GetLastPosition() );
CPPUNIT_ASSERT_EQUAL( 1, entry->GetInsertionPoint() );
entry->SetValue("something different"); // should still reset the caret
CPPUNIT_ASSERT_EQUAL( 0, entry->GetInsertionPoint() );
}
void TextEntryTestCase::Replace()
{
wxTextEntry * const entry = GetTestEntry();
entry->SetValue("Hello replace!"
"0123456789012");
entry->SetInsertionPoint(0);
entry->Replace(6, 13, "changed");
CPPUNIT_ASSERT_EQUAL("Hello changed!"
"0123456789012",
entry->GetValue());
CPPUNIT_ASSERT_EQUAL(13, entry->GetInsertionPoint());
entry->Replace(13, -1, "");
CPPUNIT_ASSERT_EQUAL("Hello changed", entry->GetValue());
CPPUNIT_ASSERT_EQUAL(13, entry->GetInsertionPoint());
entry->Replace(0, 6, "Un");
CPPUNIT_ASSERT_EQUAL("Unchanged", entry->GetValue());
CPPUNIT_ASSERT_EQUAL(2, entry->GetInsertionPoint());
}
void TextEntryTestCase::WriteText()
{
wxTextEntry * const entry = GetTestEntry();
entry->SetValue("foo");
entry->SetInsertionPoint(3);
entry->WriteText("bar");
CPPUNIT_ASSERT_EQUAL( "foobar", entry->GetValue() );
entry->SetValue("foo");
entry->SetInsertionPoint(0);
entry->WriteText("bar");
CPPUNIT_ASSERT_EQUAL( "barfoo", entry->GetValue() );
entry->SetValue("abxxxhi");
entry->SetSelection(2, 5);
entry->WriteText("cdefg");
CPPUNIT_ASSERT_EQUAL( "abcdefghi", entry->GetValue() );
CPPUNIT_ASSERT_EQUAL( 7, entry->GetInsertionPoint() );
CPPUNIT_ASSERT_EQUAL( false, entry->HasSelection() );
}
#if wxUSE_UIACTIONSIMULATOR
class TextEventHandler
{
public:
explicit TextEventHandler(wxWindow* win)
: m_win(win)
{
m_win->Bind(wxEVT_TEXT, &TextEventHandler::OnText, this);
}
~TextEventHandler()
{
m_win->Unbind(wxEVT_TEXT, &TextEventHandler::OnText, this);
}
const wxString& GetLastString() const
{
return m_string;
}
private:
void OnText(wxCommandEvent& event)
{
m_string = event.GetString();
}
wxWindow* const m_win;
wxString m_string;
};
void TextEntryTestCase::Editable()
{
wxTextEntry * const entry = GetTestEntry();
wxWindow * const window = GetTestWindow();
EventCounter updated(window, wxEVT_TEXT);
window->SetFocus();
wxYield();
#ifdef __WXGTK__
// For some reason, wxBitmapComboBox doesn't appear on the screen without
// this (due to wxTLW size hacks perhaps?). It would be nice to avoid doing
// this, but without this hack the test often (although not always) fails.
wxMilliSleep(50);
#endif // __WGTK__
// Check that we get the expected number of events.
wxUIActionSimulator sim;
sim.Text("abcdef");
wxYield();
CPPUNIT_ASSERT_EQUAL("abcdef", entry->GetValue());
CPPUNIT_ASSERT_EQUAL(6, updated.GetCount());
wxYield();
// And that the event carries the right value.
TextEventHandler handler(window);
sim.Text("g");
wxYield();
CPPUNIT_ASSERT_EQUAL("abcdefg", handler.GetLastString());
// ... even if we generate the event programmatically and whether it uses
// the same value as the control has right now
entry->SetValue("abcdefg");
CPPUNIT_ASSERT_EQUAL("abcdefg", handler.GetLastString());
// ... or not
entry->SetValue("abcdef");
CPPUNIT_ASSERT_EQUAL("abcdef", handler.GetLastString());
// Check that making the control not editable does indeed prevent it from
// being edited.
updated.Clear();
entry->SetEditable(false);
sim.Text("gh");
wxYield();
CPPUNIT_ASSERT_EQUAL("abcdef", entry->GetValue());
CPPUNIT_ASSERT_EQUAL(0, updated.GetCount());
}
#endif // wxUSE_UIACTIONSIMULATOR
void TextEntryTestCase::Hint()
{
GetTestEntry()->SetHint("This is a hint");
CPPUNIT_ASSERT_EQUAL("", GetTestEntry()->GetValue());
}
void TextEntryTestCase::CopyPaste()
{
#ifndef __WXOSX__
wxTextEntry * const entry = GetTestEntry();
entry->AppendText("sometext");
entry->SelectAll();
if(entry->CanCopy() && entry->CanPaste())
{
entry->Copy();
entry->Clear();
CPPUNIT_ASSERT(entry->IsEmpty());
wxYield();
entry->Paste();
CPPUNIT_ASSERT_EQUAL("sometext", entry->GetValue());
}
#endif
}
void TextEntryTestCase::UndoRedo()
{
wxTextEntry * const entry = GetTestEntry();
entry->AppendText("sometext");
if(entry->CanUndo())
{
entry->Undo();
CPPUNIT_ASSERT(entry->IsEmpty());
if(entry->CanRedo())
{
entry->Redo();
CPPUNIT_ASSERT_EQUAL("sometext", entry->GetValue());
}
}
}
#if wxUSE_UIACTIONSIMULATOR
namespace
{
enum ProcessEnter
{
ProcessEnter_No,
ProcessEnter_ButSkip,
ProcessEnter_WithoutSkipping
};
class TestDialog : public wxDialog
{
public:
explicit TestDialog(const TextLikeControlCreator& controlCreator,
ProcessEnter processEnter)
: wxDialog(wxTheApp->GetTopWindow(), wxID_ANY, "Test dialog"),
m_control
(
controlCreator.Create
(
this,
processEnter == ProcessEnter_No ? 0 : wxTE_PROCESS_ENTER
)
),
m_processEnter(processEnter),
m_gotEnter(false)
{
wxSizer* const sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(m_control, wxSizerFlags().Expand());
sizer->Add(CreateStdDialogButtonSizer(wxOK));
SetSizerAndFit(sizer);
CallAfter(&TestDialog::SimulateEnter);
m_timer.Bind(wxEVT_TIMER, &TestDialog::OnTimeOut, this);
m_timer.StartOnce(2000);
}
bool GotEnter() const { return m_gotEnter; }
private:
void OnTextEnter(wxCommandEvent& e)
{
m_gotEnter = true;
switch ( m_processEnter )
{
case ProcessEnter_No:
FAIL("Shouldn't be getting wxEVT_TEXT_ENTER at all");
break;
case ProcessEnter_ButSkip:
e.Skip();
break;
case ProcessEnter_WithoutSkipping:
// Close the dialog with a different exit code than what
// pressing the OK button would have generated.
EndModal(wxID_APPLY);
break;
}
}
void OnText(wxCommandEvent& WXUNUSED(e))
{
// This should only happen for the multiline text controls.
switch ( m_processEnter )
{
case ProcessEnter_No:
case ProcessEnter_ButSkip:
// We consider that the text succeeded, but in a different way,
// so use a different ID to be able to distinguish between this
// scenario and Enter activating the default button.
EndModal(wxID_CLOSE);
break;
case ProcessEnter_WithoutSkipping:
FAIL("Shouldn't be getting wxEVT_TEXT if handled");
break;
}
}
void OnTimeOut(wxTimerEvent&)
{
EndModal(wxID_CANCEL);
}
void SimulateEnter()
{
wxUIActionSimulator sim;
// Calling SetFocus() is somehow not enough to give the focus to this
// window when running this test with wxGTK, apparently because the
// dialog itself needs to be raised to the front first, so simulate a
// click doing this.
sim.MouseMove(m_control->GetScreenPosition() + wxPoint(5, 5));
wxYield();
sim.MouseClick();
wxYield();
// Note that clicking it is still not enough to give it focus with
// wxGTK either, so we still need to call SetFocus() nevertheless: but
// now it works.
m_control->SetFocus();
sim.Char(WXK_RETURN);
}
wxControl* const m_control;
const ProcessEnter m_processEnter;
wxTimer m_timer;
bool m_gotEnter;
wxDECLARE_EVENT_TABLE();
};
// Note that we must use event table macros here instead of Bind() because
// binding wxEVT_TEXT_ENTER handler for a control without wxTE_PROCESS_ENTER
// style would fail with an assertion failure, due to wx helpfully complaining
// about it.
wxBEGIN_EVENT_TABLE(TestDialog, wxDialog)
EVT_TEXT(wxID_ANY, TestDialog::OnText)
EVT_TEXT_ENTER(wxID_ANY, TestDialog::OnTextEnter)
wxEND_EVENT_TABLE()
} // anonymous namespace
void TestProcessEnter(const TextLikeControlCreator& controlCreator)
{
if ( !EnableUITests() )
{
WARN("Skipping wxTE_PROCESS_ENTER tests: wxUIActionSimulator use disabled");
return;
}
SECTION("Without wxTE_PROCESS_ENTER")
{
TestDialog dlg(controlCreator, ProcessEnter_No);
REQUIRE( dlg.ShowModal() == wxID_OK );
CHECK( !dlg.GotEnter() );
}
SECTION("With wxTE_PROCESS_ENTER but skipping")
{
TestDialog dlgProcessEnter(controlCreator, ProcessEnter_ButSkip);
REQUIRE( dlgProcessEnter.ShowModal() == wxID_OK );
CHECK( dlgProcessEnter.GotEnter() );
}
SECTION("With wxTE_PROCESS_ENTER without skipping")
{
TestDialog dlgProcessEnter(controlCreator, ProcessEnter_WithoutSkipping);
REQUIRE( dlgProcessEnter.ShowModal() == wxID_APPLY );
CHECK( dlgProcessEnter.GotEnter() );
}
SECTION("Without wxTE_PROCESS_ENTER but with wxTE_MULTILINE")
{
std::unique_ptr<TextLikeControlCreator>
multiLineCreator(controlCreator.CloneAsMultiLine());
if ( !multiLineCreator )
return;
TestDialog dlg(*multiLineCreator, ProcessEnter_No);
REQUIRE( dlg.ShowModal() == wxID_CLOSE );
CHECK( !dlg.GotEnter() );
}
SECTION("With wxTE_PROCESS_ENTER and wxTE_MULTILINE but skipping")
{
std::unique_ptr<TextLikeControlCreator>
multiLineCreator(controlCreator.CloneAsMultiLine());
if ( !multiLineCreator )
return;
TestDialog dlg(*multiLineCreator, ProcessEnter_ButSkip);
REQUIRE( dlg.ShowModal() == wxID_CLOSE );
CHECK( dlg.GotEnter() );
}
SECTION("With wxTE_PROCESS_ENTER and wxTE_MULTILINE without skipping")
{
std::unique_ptr<TextLikeControlCreator>
multiLineCreator(controlCreator.CloneAsMultiLine());
if ( !multiLineCreator )
return;
TestDialog dlg(*multiLineCreator, ProcessEnter_WithoutSkipping);
REQUIRE( dlg.ShowModal() == wxID_APPLY );
CHECK( dlg.GotEnter() );
}
}
#else // !wxUSE_UIACTIONSIMULATOR
void TestProcessEnter(const TextLikeControlCreator& WXUNUSED(controlCreator))
{
WARN("Skipping wxTE_PROCESS_ENTER tests: wxUIActionSimulator not available");
}
#endif // wxUSE_UIACTIONSIMULATOR/!wxUSE_UIACTIONSIMULATOR

View File

@@ -0,0 +1,106 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/textentrytest.h
// Purpose: Base class implementing wxTextEntry unit tests
// Author: Vadim Zeitlin
// Created: 2008-09-19 (extracted from textctrltest.cpp)
// Copyright: (c) 2007, 2008 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_TESTS_CONTROLS_TEXTENTRYTEST_H_
#define _WX_TESTS_CONTROLS_TEXTENTRYTEST_H_
class WXDLLIMPEXP_FWD_CORE wxTextEntry;
// ----------------------------------------------------------------------------
// abstract base class testing wxTextEntry methods
// ----------------------------------------------------------------------------
class TextEntryTestCase
{
public:
TextEntryTestCase() { }
virtual ~TextEntryTestCase() { }
protected:
// this function must be overridden by the derived classes to return the
// text entry object we're testing, typically this is done by creating a
// control implementing wxTextEntry interface in setUp() virtual method and
// just returning it from here
virtual wxTextEntry *GetTestEntry() const = 0;
// and this one must be overridden to return the window which implements
// wxTextEntry interface -- usually it will return the same pointer as
// GetTestEntry(), just as a different type
virtual wxWindow *GetTestWindow() const = 0;
// this should be inserted in the derived class CPPUNIT_TEST_SUITE
// definition to run all wxTextEntry tests as part of it
#define wxTEXT_ENTRY_TESTS() \
CPPUNIT_TEST( SetValue ); \
CPPUNIT_TEST( TextChangeEvents ); \
CPPUNIT_TEST( Selection ); \
CPPUNIT_TEST( InsertionPoint ); \
CPPUNIT_TEST( Replace ); \
WXUISIM_TEST( Editable ); \
CPPUNIT_TEST( Hint ); \
CPPUNIT_TEST( CopyPaste ); \
CPPUNIT_TEST( UndoRedo ); \
CPPUNIT_TEST( WriteText )
void SetValue();
void TextChangeEvents();
void Selection();
void InsertionPoint();
void Replace();
void Editable();
void Hint();
void CopyPaste();
void UndoRedo();
void WriteText();
private:
// Selection() test helper: verify that selection is as described by the
// function parameters
void AssertSelection(int from, int to, const char *sel);
// helper of AssertSelection(): check that the text selected in the control
// is the given one
//
// this is necessary to disable testing this in wxComboBox test as it
// doesn't provide any way to access the string selection directly, its
// GetStringSelection() method returns the currently selected string in the
// wxChoice part of the control, not the selected text
virtual void CheckStringSelection(const char *sel);
wxDECLARE_NO_COPY_CLASS(TextEntryTestCase);
};
// Helper used for creating the control of the specific type (currently either
// wxTextCtrl or wxComboBox) with the given flag.
class TextLikeControlCreator
{
public:
TextLikeControlCreator() {}
// Create the control of the right type using the given parent and style.
virtual wxControl* Create(wxWindow* parent, int style) const = 0;
// Return another creator similar to this one, but creating multiline
// version of the control. If the returned pointer is non-null, it must be
// deleted by the caller.
virtual TextLikeControlCreator* CloneAsMultiLine() const { return nullptr; }
// Give it a virtual dtor to avoid warnings even though this class is not
// supposed to be used polymorphically.
virtual ~TextLikeControlCreator() {}
private:
wxDECLARE_NO_COPY_CLASS(TextLikeControlCreator);
};
// Use the given control creator to check that various combinations of
// specifying and not specifying wxTE_PROCESS_ENTER and handling or not
// handling the resulting event work as expected.
void TestProcessEnter(const TextLikeControlCreator& controlCreator);
#endif // _WX_TESTS_CONTROLS_TEXTENTRYTEST_H_

View File

@@ -0,0 +1,101 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/togglebuttontest.cpp
// Purpose: wxToggleButton unit test
// Author: Steven Lamerton
// Created: 2010-07-14
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_TOGGLEBTN
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "testableframe.h"
#include "wx/uiaction.h"
#include "wx/tglbtn.h"
class ToggleButtonTestCase : public CppUnit::TestCase
{
public:
ToggleButtonTestCase() { }
void setUp() override;
void tearDown() override;
private:
CPPUNIT_TEST_SUITE( ToggleButtonTestCase );
WXUISIM_TEST( Click );
CPPUNIT_TEST( Value );
CPPUNIT_TEST_SUITE_END();
void Click();
void Value();
wxToggleButton* m_button;
wxDECLARE_NO_COPY_CLASS(ToggleButtonTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( ToggleButtonTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ToggleButtonTestCase, "ToggleButtonTestCase" );
void ToggleButtonTestCase::setUp()
{
m_button = new wxToggleButton(wxTheApp->GetTopWindow(), wxID_ANY, "wxToggleButton");
}
void ToggleButtonTestCase::tearDown()
{
wxDELETE(m_button);
}
void ToggleButtonTestCase::Click()
{
#if wxUSE_UIACTIONSIMULATOR
EventCounter clicked(m_button, wxEVT_TOGGLEBUTTON);
wxUIActionSimulator sim;
//We move in slightly to account for window decorations
sim.MouseMove(m_button->GetScreenPosition() + wxPoint(10, 10));
wxYield();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, clicked.GetCount());
CPPUNIT_ASSERT(m_button->GetValue());
clicked.Clear();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, clicked.GetCount());
CPPUNIT_ASSERT(!m_button->GetValue());
#endif
}
void ToggleButtonTestCase::Value()
{
EventCounter clicked(m_button, wxEVT_BUTTON);
m_button->SetValue(true);
CPPUNIT_ASSERT(m_button->GetValue());
m_button->SetValue(false);
CPPUNIT_ASSERT(!m_button->GetValue());
CPPUNIT_ASSERT_EQUAL( 0, clicked.GetCount() );
}
#endif //wxUSE_TOGGLEBTN

View File

@@ -0,0 +1,79 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/toolbooktest.cpp
// Purpose: wxToolbook unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_TOOLBOOK
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/toolbook.h"
#include "wx/toolbar.h"
#include "bookctrlbasetest.h"
class ToolbookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase
{
public:
ToolbookTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxBookCtrlBase *GetBase() const override { return m_toolbook; }
virtual wxEventType GetChangedEvent() const override
{ return wxEVT_TOOLBOOK_PAGE_CHANGED; }
virtual wxEventType GetChangingEvent() const override
{ return wxEVT_TOOLBOOK_PAGE_CHANGING; }
virtual void Realize() override { m_toolbook->GetToolBar()->Realize(); }
CPPUNIT_TEST_SUITE( ToolbookTestCase );
wxBOOK_CTRL_BASE_TESTS();
CPPUNIT_TEST( ToolBar );
CPPUNIT_TEST_SUITE_END();
void ToolBar();
wxToolbook *m_toolbook;
wxDECLARE_NO_COPY_CLASS(ToolbookTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( ToolbookTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( ToolbookTestCase, "ToolbookTestCase" );
void ToolbookTestCase::setUp()
{
m_toolbook = new wxToolbook(wxTheApp->GetTopWindow(), wxID_ANY, wxDefaultPosition, wxSize(400, 200));
AddPanels();
}
void ToolbookTestCase::tearDown()
{
wxDELETE(m_toolbook);
}
void ToolbookTestCase::ToolBar()
{
wxToolBar* toolbar = static_cast<wxToolBar*>(m_toolbook->GetToolBar());
CPPUNIT_ASSERT(toolbar);
CPPUNIT_ASSERT_EQUAL(3, toolbar->GetToolsCount());
}
#endif //wxUSE_TOOLBOOK

View File

@@ -0,0 +1,159 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/treebooktest.cpp
// Purpose: wxtreebook unit test
// Author: Steven Lamerton
// Created: 2010-07-02
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_TREEBOOK
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/panel.h"
#endif // WX_PRECOMP
#include "wx/treebook.h"
#include "bookctrlbasetest.h"
class TreebookTestCase : public BookCtrlBaseTestCase, public CppUnit::TestCase
{
public:
TreebookTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
virtual wxBookCtrlBase *GetBase() const override { return m_treebook; }
virtual wxEventType GetChangedEvent() const override
{ return wxEVT_TREEBOOK_PAGE_CHANGED; }
virtual wxEventType GetChangingEvent() const override
{ return wxEVT_TREEBOOK_PAGE_CHANGING; }
CPPUNIT_TEST_SUITE( TreebookTestCase );
wxBOOK_CTRL_BASE_TESTS();
CPPUNIT_TEST( Image );
CPPUNIT_TEST( SubPages );
CPPUNIT_TEST( ContainerPage );
CPPUNIT_TEST( Expand );
CPPUNIT_TEST( Delete );
CPPUNIT_TEST_SUITE_END();
void SubPages();
void ContainerPage();
void Expand();
void Delete();
wxTreebook *m_treebook;
wxDECLARE_NO_COPY_CLASS(TreebookTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( TreebookTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TreebookTestCase, "TreebookTestCase" );
void TreebookTestCase::setUp()
{
m_treebook = new wxTreebook(wxTheApp->GetTopWindow(), wxID_ANY);
AddPanels();
}
void TreebookTestCase::tearDown()
{
wxDELETE(m_treebook);
}
void TreebookTestCase::SubPages()
{
wxPanel* subpanel1 = new wxPanel(m_treebook);
wxPanel* subpanel2 = new wxPanel(m_treebook);
wxPanel* subpanel3 = new wxPanel(m_treebook);
m_treebook->AddSubPage(subpanel1, "Subpanel 1", false, 0);
CPPUNIT_ASSERT_EQUAL(2, m_treebook->GetPageParent(3));
m_treebook->InsertSubPage(1, subpanel2, "Subpanel 2", false, 1);
CPPUNIT_ASSERT_EQUAL(1, m_treebook->GetPageParent(2));
m_treebook->AddSubPage(subpanel3, "Subpanel 3", false, 2);
CPPUNIT_ASSERT_EQUAL(3, m_treebook->GetPageParent(5));
}
void TreebookTestCase::ContainerPage()
{
// Get rid of the pages added in setUp().
m_treebook->DeleteAllPages();
CHECK( m_treebook->GetPageCount() == 0 );
// Adding a page without the associated window should be allowed.
REQUIRE_NOTHROW( m_treebook->AddPage(nullptr, "Container page") );
CHECK( m_treebook->GetPageParent(0) == -1 );
m_treebook->AddSubPage(new wxPanel(m_treebook), "Child page");
CHECK( m_treebook->GetPageParent(1) == 0 );
}
void TreebookTestCase::Expand()
{
wxPanel* subpanel1 = new wxPanel(m_treebook);
wxPanel* subpanel2 = new wxPanel(m_treebook);
wxPanel* subpanel3 = new wxPanel(m_treebook);
m_treebook->AddSubPage(subpanel1, "Subpanel 1", false, 0);
m_treebook->InsertSubPage(1, subpanel2, "Subpanel 2", false, 1);
m_treebook->AddSubPage(subpanel3, "Subpanel 3", false, 2);
CPPUNIT_ASSERT(!m_treebook->IsNodeExpanded(1));
CPPUNIT_ASSERT(!m_treebook->IsNodeExpanded(3));
m_treebook->CollapseNode(1);
CPPUNIT_ASSERT(!m_treebook->IsNodeExpanded(1));
m_treebook->ExpandNode(3, false);
CPPUNIT_ASSERT(!m_treebook->IsNodeExpanded(3));
m_treebook->ExpandNode(1);
CPPUNIT_ASSERT(m_treebook->IsNodeExpanded(1));
}
void TreebookTestCase::Delete()
{
wxPanel* subpanel1 = new wxPanel(m_treebook);
wxPanel* subpanel2 = new wxPanel(m_treebook);
wxPanel* subpanel3 = new wxPanel(m_treebook);
m_treebook->AddSubPage(subpanel1, "Subpanel 1", false, 0);
m_treebook->InsertSubPage(1, subpanel2, "Subpanel 2", false, 1);
m_treebook->AddSubPage(subpanel3, "Subpanel 3", false, 2);
CPPUNIT_ASSERT_EQUAL(6, m_treebook->GetPageCount());
m_treebook->DeletePage(3);
CPPUNIT_ASSERT_EQUAL(3, m_treebook->GetPageCount());
m_treebook->DeletePage(1);
CPPUNIT_ASSERT_EQUAL(1, m_treebook->GetPageCount());
m_treebook->DeletePage(0);
CPPUNIT_ASSERT_EQUAL(0, m_treebook->GetPageCount());
}
#endif // wxUSE_TREEBOOK

View File

@@ -0,0 +1,705 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/treectrltest.cpp
// Purpose: wxTreeCtrl unit test
// Author: Vadim Zeitlin
// Created: 2008-11-26
// Copyright: (c) 2008 Vadim Zeitlin <vadim@wxwidgets.org>
// (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_TREECTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/artprov.h"
#include "wx/imaglist.h"
#include "wx/treectrl.h"
#include "wx/uiaction.h"
#include "testableframe.h"
#include "waitfor.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class TreeCtrlTestCase
{
public:
explicit TreeCtrlTestCase(int exStyle = 0)
{
m_tree = new wxTreeCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
wxDefaultPosition,
wxSize(400, 200),
wxTR_DEFAULT_STYLE | wxTR_EDIT_LABELS | exStyle);
m_root = m_tree->AddRoot("root");
m_child1 = m_tree->AppendItem(m_root, "child1");
m_child2 = m_tree->AppendItem(m_root, "child2");
m_grandchild = m_tree->AppendItem(m_child1, "grandchild");
m_tree->SetSize(400, 200);
m_tree->ExpandAll();
m_tree->Refresh();
m_tree->Update();
}
~TreeCtrlTestCase()
{
delete m_tree;
}
protected:
// the tree control itself
wxTreeCtrl *m_tree = nullptr;
// and some of its items
wxTreeItemId m_root,
m_child1,
m_child2,
m_grandchild;
wxDECLARE_NO_COPY_CLASS(TreeCtrlTestCase);
};
// Notice that toggling the wxTR_HIDE_ROOT window style with ToggleWindowStyle
// has no effect under wxMSW if wxTreeCtrl::AddRoot() has already been called.
// So we need this fixture (used by HasChildren and GetCount below) to create
// the wxTreeCtrl with this style before AddRoot() is called.
class TreeCtrlHideRootTestCase : public TreeCtrlTestCase
{
public:
TreeCtrlHideRootTestCase() : TreeCtrlTestCase(wxTR_HIDE_ROOT)
{
}
};
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
TEST_CASE_METHOD(TreeCtrlHideRootTestCase, "wxTreeCtrl::HasChildren", "[treectrl]")
{
CHECK( m_tree->HasChildren(m_root) );
CHECK( m_tree->HasChildren(m_child1) );
CHECK_FALSE( m_tree->HasChildren(m_child2) );
CHECK_FALSE( m_tree->HasChildren(m_grandchild) );
}
TEST_CASE_METHOD(TreeCtrlHideRootTestCase, "wxTreeCtrl::GetCount", "[treectrl]")
{
CHECK(m_tree->GetCount() == 3);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::SelectItemSingle", "[treectrl]")
{
// this test should be only ran in single-selection control
CHECK_FALSE( m_tree->HasFlag(wxTR_MULTIPLE) );
// initially nothing is selected
CHECK_FALSE( m_tree->IsSelected(m_child1) );
// selecting an item should make it selected
m_tree->SelectItem(m_child1);
CHECK( m_tree->IsSelected(m_child1) );
// selecting it again shouldn't change anything
m_tree->SelectItem(m_child1);
CHECK( m_tree->IsSelected(m_child1) );
// selecting another item should switch the selection to it
m_tree->SelectItem(m_child2);
CHECK_FALSE( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
// selecting it again still shouldn't change anything
m_tree->SelectItem(m_child2);
CHECK_FALSE( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
// deselecting an item should remove the selection entirely
m_tree->UnselectItem(m_child2);
CHECK_FALSE( m_tree->IsSelected(m_child1) );
CHECK_FALSE( m_tree->IsSelected(m_child2) );
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::SelectItemMulti", "[treectrl]")
{
// this test should be only ran in multi-selection control
m_tree->ToggleWindowStyle(wxTR_MULTIPLE);
// initially nothing is selected
CHECK_FALSE( m_tree->IsSelected(m_child1) );
// selecting an item should make it selected
m_tree->SelectItem(m_child1);
CHECK( m_tree->IsSelected(m_child1) );
// selecting it again shouldn't change anything
m_tree->SelectItem(m_child1);
CHECK( m_tree->IsSelected(m_child1) );
// selecting another item shouldn't deselect the previously selected one
m_tree->SelectItem(m_child2);
CHECK( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
// selecting it again still shouldn't change anything
m_tree->SelectItem(m_child2);
CHECK( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
// deselecting one of the items should leave the others selected
m_tree->UnselectItem(m_child1);
CHECK_FALSE( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
// collapsing a branch with selected items should still leave them selected
m_tree->Expand(m_child1);
m_tree->SelectItem(m_grandchild);
CHECK( m_tree->IsSelected(m_grandchild) );
m_tree->Collapse(m_child1);
CHECK( m_tree->IsSelected(m_grandchild) );
m_tree->Expand(m_child1);
CHECK( m_tree->IsSelected(m_grandchild) );
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::DeleteItem", "[treectrl]")
{
EventCounter deleteitem(m_tree, wxEVT_TREE_DELETE_ITEM);
wxTreeItemId todelete = m_tree->AppendItem(m_root, "deleteme");
m_tree->AppendItem(todelete, "deleteme2");
m_tree->Delete(todelete);
CHECK(deleteitem.GetCount() == 2);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::DeleteChildren", "[treectrl]")
{
EventCounter deletechildren(m_tree, wxEVT_TREE_DELETE_ITEM);
m_tree->AppendItem(m_child1, "another grandchild");
m_tree->DeleteChildren(m_child1);
CHECK( deletechildren.GetCount() == 2 );
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::DeleteAllItems", "[treectrl]")
{
EventCounter deleteall(m_tree, wxEVT_TREE_DELETE_ITEM);
m_tree->DeleteAllItems();
CHECK( deleteall.GetCount() == 4 );
}
#if wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::ItemClick", "[treectrl]")
{
EventCounter activated(m_tree, wxEVT_TREE_ITEM_ACTIVATED);
EventCounter rclick(m_tree, wxEVT_TREE_ITEM_RIGHT_CLICK);
wxUIActionSimulator sim;
wxRect pos;
m_tree->GetBoundingRect(m_child1, pos, true);
// We move in slightly so we are not on the edge
wxPoint point = m_tree->ClientToScreen(pos.GetPosition()) + wxPoint(4, 4);
sim.MouseMove(point);
wxYield();
sim.MouseDblClick();
wxYield();
sim.MouseClick(wxMOUSE_BTN_RIGHT);
wxYield();
CHECK(activated.GetCount() == 1);
CHECK(rclick.GetCount() == 1);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::LabelEdit", "[treectrl]")
{
EventCounter beginedit(m_tree, wxEVT_TREE_BEGIN_LABEL_EDIT);
EventCounter endedit(m_tree, wxEVT_TREE_END_LABEL_EDIT);
wxUIActionSimulator sim;
#ifdef __WXQT__
m_tree->SetFocus();
wxYield();
#endif
m_tree->SetFocusedItem(m_tree->GetRootItem());
m_tree->EditLabel(m_tree->GetRootItem());
sim.Text("newroottext");
wxYield();
CHECK(beginedit.GetCount() == 1);
sim.Char(WXK_RETURN);
wxYield();
CHECK(endedit.GetCount() == 1);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::KeyDown", "[treectrl]")
{
EventCounter keydown(m_tree, wxEVT_TREE_KEY_DOWN);
wxUIActionSimulator sim;
m_tree->SetFocus();
wxYield();
sim.Text("aAbB");
wxYield();
CHECK(keydown.GetCount() == 6);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::CollapseExpandEvents", "[treectrl]")
{
#ifdef __WXGTK__
// Works locally, but not when run on Travis CI.
if ( IsAutomaticTest() )
return;
#endif
m_tree->CollapseAll();
EventCounter collapsed(m_tree, wxEVT_TREE_ITEM_COLLAPSED);
EventCounter collapsing(m_tree, wxEVT_TREE_ITEM_COLLAPSING);
EventCounter expanded(m_tree, wxEVT_TREE_ITEM_EXPANDED);
EventCounter expanding(m_tree, wxEVT_TREE_ITEM_EXPANDING);
wxUIActionSimulator sim;
wxRect pos;
m_tree->GetBoundingRect(m_root, pos, true);
// We move in slightly so we are not on the edge
wxPoint point = m_tree->ClientToScreen(pos.GetPosition()) + wxPoint(4, 4);
sim.MouseMove(point);
wxYield();
sim.MouseDblClick();
wxYield();
CHECK(expanding.GetCount() == 1);
CHECK(expanded.GetCount() == 1);
#ifdef __WXGTK__
// Don't even know the reason why, but GTK has to sleep
// no less than 1200 for the test case to succeed.
wxMilliSleep(1200);
#endif
sim.MouseDblClick();
wxYield();
CHECK(collapsing.GetCount() == 1);
CHECK(collapsed.GetCount() == 1);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::SelectionChange", "[treectrl]")
{
m_tree->ExpandAll();
// This is currently needed to work around a problem under wxMSW: clicking
// on an item in an unfocused control generates two selection change events
// because of the SetFocus() call in TVN_SELCHANGED handler in wxMSW code.
// This is, of course, wrong on its own, but fixing it without breaking
// anything else is non-obvious, so for now at least work around this
// problem in the test.
m_tree->SetFocus();
bool vetoChange = false;
SECTION("Without veto selection change"){ }
SECTION("With veto selection change")
{
vetoChange = true;
}
int changed = 0;
int changing = 0;
auto handler = [&](wxTreeEvent& event)
{
const auto eventType = event.GetEventType();
if ( eventType == wxEVT_TREE_SEL_CHANGING )
{
++changing;
if ( vetoChange && changed == 1 )
{
event.Veto();
}
}
else if ( eventType == wxEVT_TREE_SEL_CHANGED )
{
++changed;
}
};
m_tree->Bind(wxEVT_TREE_SEL_CHANGED, handler);
m_tree->Bind(wxEVT_TREE_SEL_CHANGING, handler);
wxUIActionSimulator sim;
wxRect poschild1, poschild2;
m_tree->GetBoundingRect(m_child1, poschild1, true);
m_tree->GetBoundingRect(m_child2, poschild2, true);
// We move in slightly so we are not on the edge
wxPoint point1 = m_tree->ClientToScreen(poschild1.GetPosition()) + wxPoint(4, 4);
wxPoint point2 = m_tree->ClientToScreen(poschild2.GetPosition()) + wxPoint(4, 4);
sim.MouseMove(point1);
wxYield();
sim.MouseClick();
wxYield();
CHECK(changed == 1);
CHECK(changing == 1);
sim.MouseMove(point2);
wxYield();
sim.MouseClick();
wxYield();
CHECK(changed == (vetoChange ? 1 : 2));
CHECK(changing == 2);
if ( vetoChange )
{
CHECK( m_tree->IsSelected(m_child1) );
CHECK_FALSE( m_tree->IsSelected(m_child2) );
}
else
{
CHECK_FALSE( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
}
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::SelectItemMultiInteractive", "[treectrl]")
{
#if defined(__WXGTK__) && !defined(__WXGTK3__)
// FIXME: This test fails on GitHub CI under wxGTK2 although works fine on
// development machine, no idea why though!
if ( IsAutomaticTest() )
return;
#endif // wxGTK2
// this test should be only ran in multi-selection control
m_tree->ToggleWindowStyle(wxTR_MULTIPLE);
m_tree->ExpandAll();
// This is currently needed to work around a problem under wxMSW: clicking
// on an item in an unfocused control generates two selection change events
// because of the SetFocus() call in TVN_SELCHANGED handler in wxMSW code.
// This is, of course, wrong on its own, but fixing it without breaking
// anything else is non-obvious, so for now at least work around this
// problem in the test.
m_tree->SetFocus();
EventCounter beginedit(m_tree, wxEVT_TREE_BEGIN_LABEL_EDIT);
wxUIActionSimulator sim;
wxRect poschild1, poschild2;
m_tree->GetBoundingRect(m_child1, poschild1, true);
m_tree->GetBoundingRect(m_child2, poschild2, true);
// We move in slightly so we are not on the edge
wxPoint point1 = m_tree->ClientToScreen(poschild1.GetPosition()) + wxPoint(4, 4);
wxPoint point2 = m_tree->ClientToScreen(poschild2.GetPosition()) + wxPoint(4, 4);
sim.MouseMove(point1);
wxYield();
sim.MouseClick();
wxYield();
sim.MouseMove(point2);
wxYield();
sim.KeyDown(WXK_CONTROL);
sim.MouseClick();
sim.KeyUp(WXK_CONTROL);
wxYield();
// m_child1 and m_child2 should be selected.
CHECK( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
CHECK( beginedit.GetCount() == 0 );
// Time needed (in ms) for the editor to display. The test will not pass
// if the value is less than 400, 510, 800 under wxQt, wxGTK, wxMSW resp.
const int BEGIN_EDIT_TIMEOUT = 800;
YieldForAWhile(BEGIN_EDIT_TIMEOUT);
sim.MouseClick();
YieldForAWhile(BEGIN_EDIT_TIMEOUT);
// Only m_child2 should be selected now.
CHECK_FALSE( m_tree->IsSelected(m_child1) );
CHECK( m_tree->IsSelected(m_child2) );
CHECK( beginedit.GetCount() == 0 ); // No editing should take place in the event of deselection.
sim.MouseClick();
YieldForAWhile(BEGIN_EDIT_TIMEOUT);
CHECK( beginedit.GetCount() == 1 ); // Start editing as usual.
sim.Char(WXK_RETURN); // End editing and close the editor.
wxYield();
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Menu", "[treectrl]")
{
EventCounter menu(m_tree, wxEVT_TREE_ITEM_MENU);
wxUIActionSimulator sim;
wxRect pos;
m_tree->GetBoundingRect(m_child1, pos, true);
// We move in slightly so we are not on the edge
wxPoint point = m_tree->ClientToScreen(pos.GetPosition()) + wxPoint(4, 4);
sim.MouseMove(point);
wxYield();
sim.MouseClick(wxMOUSE_BTN_RIGHT);
wxYield();
CHECK(menu.GetCount() == 1);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::KeyNavigation", "[treectrl]")
{
wxUIActionSimulator sim;
m_tree->CollapseAll();
m_tree->SelectItem(m_root);
wxYield();
m_tree->SetFocus();
sim.Char(WXK_RIGHT);
wxYield();
CHECK(m_tree->IsExpanded(m_root));
#ifdef wxHAS_GENERIC_TREECTRL
sim.Char('-');
#else
sim.Char(WXK_LEFT);
#endif
wxYield();
CHECK(!m_tree->IsExpanded(m_root));
wxYield();
sim.Char(WXK_RIGHT);
sim.Char(WXK_DOWN);
wxYield();
CHECK(m_tree->GetSelection() == m_child1);
sim.Char(WXK_DOWN);
wxYield();
CHECK(m_tree->GetSelection() == m_child2);
}
#endif // wxUSE_UIACTIONSIMULATOR
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::ItemData", "[treectrl]")
{
wxTreeItemData* child1data = new wxTreeItemData();
wxTreeItemData* appenddata = new wxTreeItemData();
wxTreeItemData* insertdata = new wxTreeItemData();
m_tree->SetItemData(m_child1, child1data);
CHECK(m_tree->GetItemData(m_child1) == child1data);
CHECK(child1data->GetId() == m_child1);
wxTreeItemId append = m_tree->AppendItem(m_root, "new", -1, -1, appenddata);
CHECK(m_tree->GetItemData(append) == appenddata);
CHECK(appenddata->GetId() == append);
wxTreeItemId insert = m_tree->InsertItem(m_root, m_child1, "new", -1, -1,
insertdata);
CHECK(m_tree->GetItemData(insert) == insertdata);
CHECK(insertdata->GetId() == insert);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Iteration", "[treectrl]")
{
// Get first / next / last child
wxTreeItemIdValue cookie;
CHECK(m_tree->GetFirstChild(m_root, cookie) == m_child1);
CHECK(m_tree->GetNextChild(m_root, cookie) == m_tree->GetLastChild(m_root));
CHECK(m_tree->GetLastChild(m_root) == m_child2);
// Get next / previous sibling
CHECK(m_tree->GetNextSibling(m_child1) == m_child2);
CHECK(m_tree->GetPrevSibling(m_child2) == m_child1);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Parent", "[treectrl]")
{
CHECK(m_tree->GetRootItem() == m_root);
CHECK(m_tree->GetItemParent(m_child1) == m_root);
CHECK(m_tree->GetItemParent(m_child2) == m_root);
CHECK(m_tree->GetItemParent(m_grandchild) == m_child1);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::CollapseExpand", "[treectrl]")
{
m_tree->ExpandAll();
CHECK(m_tree->IsExpanded(m_root));
CHECK(m_tree->IsExpanded(m_child1));
m_tree->CollapseAll();
CHECK_FALSE(m_tree->IsExpanded(m_root));
CHECK_FALSE(m_tree->IsExpanded(m_child1));
m_tree->ExpandAllChildren(m_root);
CHECK(m_tree->IsExpanded(m_root));
CHECK(m_tree->IsExpanded(m_child1));
m_tree->CollapseAllChildren(m_child1);
CHECK_FALSE(m_tree->IsExpanded(m_child1));
m_tree->Expand(m_child1);
CHECK(m_tree->IsExpanded(m_child1));
m_tree->Collapse(m_root);
CHECK_FALSE(m_tree->IsExpanded(m_root));
CHECK(m_tree->IsExpanded(m_child1));
m_tree->CollapseAndReset(m_root);
CHECK_FALSE(m_tree->IsExpanded(m_root));
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::AssignImageList", "[treectrl]")
{
wxSize size(16, 16);
wxImageList *imagelist = new wxImageList(size.x, size.y);
imagelist->Add(wxArtProvider::GetIcon(wxART_QUESTION, wxART_OTHER, size));
wxImageList *statelist = new wxImageList(size.x, size.y);
statelist->Add(wxArtProvider::GetIcon(wxART_ERROR, wxART_OTHER, size));
m_tree->AssignImageList(imagelist);
m_tree->AssignStateImageList(statelist);
CHECK(m_tree->GetImageList() == imagelist);
CHECK(m_tree->GetStateImageList() == statelist);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Focus", "[treectrl]")
{
m_tree->SetFocusedItem(m_child1);
CHECK(m_tree->GetFocusedItem() == m_child1);
m_tree->ClearFocusedItem();
CHECK_FALSE(m_tree->GetFocusedItem());
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Bold", "[treectrl]")
{
CHECK_FALSE(m_tree->IsBold(m_child1));
m_tree->SetItemBold(m_child1);
CHECK(m_tree->IsBold(m_child1));
m_tree->SetItemBold(m_child1, false);
CHECK_FALSE(m_tree->IsBold(m_child1));
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Visible", "[treectrl]")
{
m_tree->CollapseAll();
CHECK(m_tree->IsVisible(m_root));
CHECK_FALSE(m_tree->IsVisible(m_child1));
m_tree->EnsureVisible(m_grandchild);
CHECK(m_tree->IsVisible(m_grandchild));
m_tree->ExpandAll();
CHECK(m_tree->GetFirstVisibleItem() == m_root);
CHECK(m_tree->GetNextVisible(m_root) == m_child1);
CHECK(m_tree->GetNextVisible(m_child1) == m_grandchild);
CHECK(m_tree->GetNextVisible(m_grandchild) == m_child2);
CHECK_FALSE(m_tree->GetNextVisible(m_child2));
CHECK_FALSE(m_tree->GetPrevVisible(m_root));
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Scroll", "[treectrl]")
{
// This trivial test just checks that calling ScrollTo() with the root item
// doesn't crash any longer, as it used to do when the root item was hidden.
m_tree->ScrollTo(m_root);
}
TEST_CASE_METHOD(TreeCtrlTestCase, "wxTreeCtrl::Sort", "[treectrl]")
{
wxTreeItemId zitem = m_tree->AppendItem(m_root, "zzzz");
wxTreeItemId aitem = m_tree->AppendItem(m_root, "aaaa");
m_tree->SortChildren(m_root);
wxTreeItemIdValue cookie;
CHECK(m_tree->GetFirstChild(m_root, cookie) == aitem);
CHECK(m_tree->GetNextChild(m_root, cookie) == m_child1);
CHECK(m_tree->GetNextChild(m_root, cookie) == m_child2);
CHECK(m_tree->GetNextChild(m_root, cookie) == zitem);
}
#endif //wxUSE_TREECTRL

View File

@@ -0,0 +1,231 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/treelistctrltest.cpp
// Purpose: wxTreeListCtrl unit test.
// Author: Vadim Zeitlin
// Created: 2011-08-27
// Copyright: (c) 2011 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_TREELISTCTRL
#include "wx/treelist.h"
#include "wx/app.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class TreeListCtrlTestCase : public CppUnit::TestCase
{
public:
TreeListCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
CPPUNIT_TEST_SUITE( TreeListCtrlTestCase );
CPPUNIT_TEST( Traversal );
CPPUNIT_TEST( ItemText );
CPPUNIT_TEST( ItemCheck );
CPPUNIT_TEST_SUITE_END();
// Create the control with the given style.
void Create(long style);
// Add an item to the tree and increment m_numItems.
wxTreeListItem AddItem(const char *label,
wxTreeListItem parent = wxTreeListItem(),
const char *numFiles = "",
const char *size = "");
// Tests:
void Traversal();
void ItemText();
void ItemCheck();
// The control itself.
wxTreeListCtrl *m_treelist;
// And some of its items.
wxTreeListItem m_code,
m_code_osx,
m_code_osx_cocoa;
// Also the total number of items in it initially
unsigned m_numItems;
wxDECLARE_NO_COPY_CLASS(TreeListCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( TreeListCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( TreeListCtrlTestCase, "TreeListCtrlTestCase" );
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
wxTreeListItem
TreeListCtrlTestCase::AddItem(const char *label,
wxTreeListItem parent,
const char *numFiles,
const char *size)
{
if ( !parent.IsOk() )
parent = m_treelist->GetRootItem();
wxTreeListItem item = m_treelist->AppendItem(parent, label);
m_treelist->SetItemText(item, 1, numFiles);
m_treelist->SetItemText(item, 2, size);
m_numItems++;
return item;
}
void TreeListCtrlTestCase::Create(long style)
{
m_treelist = new wxTreeListCtrl(wxTheApp->GetTopWindow(),
wxID_ANY,
wxDefaultPosition,
wxSize(400, 200),
style);
m_treelist->AppendColumn("Component");
m_treelist->AppendColumn("# Files");
m_treelist->AppendColumn("Size");
// Fill the control with the same data as used in the treelist sample:
m_code = AddItem("Code");
AddItem("wxMSW", m_code, "313", "3.94 MiB");
AddItem("wxGTK", m_code, "180", "1.66 MiB");
m_code_osx = AddItem("wxOSX", m_code, "265", "2.36 MiB");
AddItem("Core", m_code_osx, "31", "347 KiB");
AddItem("Carbon", m_code_osx, "91", "1.34 MiB");
m_code_osx_cocoa = AddItem("Cocoa", m_code_osx, "46", "512 KiB");
wxTreeListItem Documentation = AddItem("Documentation");
AddItem("HTML", Documentation, "many");
AddItem("CHM", Documentation, "1");
wxTreeListItem Samples = AddItem("Samples");
AddItem("minimal", Samples, "1", "7 KiB");
AddItem("widgets", Samples, "28", "419 KiB");
m_treelist->Refresh();
m_treelist->Update();
}
void TreeListCtrlTestCase::setUp()
{
m_numItems = 0;
Create(wxTL_MULTIPLE | wxTL_3STATE);
}
void TreeListCtrlTestCase::tearDown()
{
delete m_treelist;
m_treelist = nullptr;
}
// ----------------------------------------------------------------------------
// the tests themselves
// ----------------------------------------------------------------------------
// Test various tree traversal methods.
void TreeListCtrlTestCase::Traversal()
{
// GetParent() tests:
wxTreeListItem root = m_treelist->GetRootItem();
CPPUNIT_ASSERT( !m_treelist->GetItemParent(root) );
CPPUNIT_ASSERT_EQUAL( root, m_treelist->GetItemParent(m_code) );
CPPUNIT_ASSERT_EQUAL( m_code, m_treelist->GetItemParent(m_code_osx) );
// GetFirstChild() and GetNextSibling() tests:
CPPUNIT_ASSERT_EQUAL( m_code, m_treelist->GetFirstChild(root) );
CPPUNIT_ASSERT_EQUAL
(
m_code_osx,
m_treelist->GetNextSibling
(
m_treelist->GetNextSibling
(
m_treelist->GetFirstChild(m_code)
)
)
);
// Get{First,Next}Item() test:
unsigned numItems = 0;
for ( wxTreeListItem item = m_treelist->GetFirstItem();
item.IsOk();
item = m_treelist->GetNextItem(item) )
{
numItems++;
}
CPPUNIT_ASSERT_EQUAL( m_numItems, numItems );
}
// Test accessing items text.
void TreeListCtrlTestCase::ItemText()
{
CPPUNIT_ASSERT_EQUAL( "Cocoa", m_treelist->GetItemText(m_code_osx_cocoa) );
CPPUNIT_ASSERT_EQUAL( "46", m_treelist->GetItemText(m_code_osx_cocoa, 1) );
m_treelist->SetItemText(m_code_osx_cocoa, "wxCocoa");
CPPUNIT_ASSERT_EQUAL( "wxCocoa", m_treelist->GetItemText(m_code_osx_cocoa) );
m_treelist->SetItemText(m_code_osx_cocoa, 1, "47");
CPPUNIT_ASSERT_EQUAL( "47", m_treelist->GetItemText(m_code_osx_cocoa, 1) );
}
// Test checking and unchecking items.
void TreeListCtrlTestCase::ItemCheck()
{
CPPUNIT_ASSERT_EQUAL( wxCHK_UNCHECKED,
m_treelist->GetCheckedState(m_code) );
m_treelist->CheckItemRecursively(m_code);
CPPUNIT_ASSERT_EQUAL( wxCHK_CHECKED,
m_treelist->GetCheckedState(m_code) );
CPPUNIT_ASSERT_EQUAL( wxCHK_CHECKED,
m_treelist->GetCheckedState(m_code_osx) );
CPPUNIT_ASSERT_EQUAL( wxCHK_CHECKED,
m_treelist->GetCheckedState(m_code_osx_cocoa) );
m_treelist->UncheckItem(m_code_osx_cocoa);
CPPUNIT_ASSERT_EQUAL( wxCHK_UNCHECKED,
m_treelist->GetCheckedState(m_code_osx_cocoa) );
m_treelist->UpdateItemParentStateRecursively(m_code_osx_cocoa);
CPPUNIT_ASSERT_EQUAL( wxCHK_UNDETERMINED,
m_treelist->GetCheckedState(m_code_osx) );
CPPUNIT_ASSERT_EQUAL( wxCHK_UNDETERMINED,
m_treelist->GetCheckedState(m_code) );
m_treelist->CheckItemRecursively(m_code_osx, wxCHK_UNCHECKED);
m_treelist->UpdateItemParentStateRecursively(m_code_osx_cocoa);
CPPUNIT_ASSERT_EQUAL( wxCHK_UNCHECKED,
m_treelist->GetCheckedState(m_code_osx) );
CPPUNIT_ASSERT_EQUAL( wxCHK_UNDETERMINED,
m_treelist->GetCheckedState(m_code) );
}
#endif // wxUSE_TREELISTCTRL

View File

@@ -0,0 +1,152 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/virtlistctrltest.cpp
// Purpose: wxListCtrl unit tests for virtual mode
// Author: Vadim Zeitlin
// Created: 2010-11-13
// Copyright: (c) 2010 Vadim Zeitlin <vadim@wxwidgets.org>
///////////////////////////////////////////////////////////////////////////////
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
#include "testprec.h"
#if wxUSE_LISTCTRL
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "wx/listctrl.h"
#include "testableframe.h"
#include "wx/uiaction.h"
// ----------------------------------------------------------------------------
// test class
// ----------------------------------------------------------------------------
class VirtListCtrlTestCase : public CppUnit::TestCase
{
public:
VirtListCtrlTestCase() { }
virtual void setUp() override;
virtual void tearDown() override;
private:
CPPUNIT_TEST_SUITE( VirtListCtrlTestCase );
CPPUNIT_TEST( UpdateSelection );
WXUISIM_TEST( DeselectedEvent );
CPPUNIT_TEST_SUITE_END();
void UpdateSelection();
void DeselectedEvent();
wxListCtrl *m_list;
wxDECLARE_NO_COPY_CLASS(VirtListCtrlTestCase);
};
// register in the unnamed registry so that these tests are run by default
CPPUNIT_TEST_SUITE_REGISTRATION( VirtListCtrlTestCase );
// also include in its own registry so that these tests can be run alone
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( VirtListCtrlTestCase, "VirtListCtrlTestCase" );
// ----------------------------------------------------------------------------
// test initialization
// ----------------------------------------------------------------------------
void VirtListCtrlTestCase::setUp()
{
// Define a class overriding OnGetItemText() which must be overridden for
// any virtual list control.
class VirtListCtrl : public wxListCtrl
{
public:
VirtListCtrl()
: wxListCtrl(wxTheApp->GetTopWindow(), wxID_ANY,
wxPoint(0, 0), wxSize(400, 200),
wxLC_REPORT | wxLC_VIRTUAL)
{
}
protected:
virtual wxString OnGetItemText(long item, long column) const override
{
return wxString::Format("Row %ld, col %ld", item, column);
}
};
m_list = new VirtListCtrl;
m_list->AppendColumn("Col0");
}
void VirtListCtrlTestCase::tearDown()
{
delete m_list;
m_list = nullptr;
}
void VirtListCtrlTestCase::UpdateSelection()
{
m_list->SetItemCount(10);
CPPUNIT_ASSERT_EQUAL( 0, m_list->GetSelectedItemCount() );
m_list->SetItemState(7, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
CPPUNIT_ASSERT_EQUAL( 1, m_list->GetSelectedItemCount() );
m_list->SetItemState(0, wxLIST_STATE_SELECTED, wxLIST_STATE_SELECTED);
CPPUNIT_ASSERT_EQUAL( 2, m_list->GetSelectedItemCount() );
// The item 7 is now invalid and so shouldn't be counted as selected any
// more. Notice that under wxQt, the selection is lost/cleared when the
// model is reset
m_list->SetItemCount(5);
#ifndef __WXQT__
CPPUNIT_ASSERT_EQUAL( 1, m_list->GetSelectedItemCount() );
#else
CPPUNIT_ASSERT_EQUAL( 0, m_list->GetSelectedItemCount() );
#endif
}
void VirtListCtrlTestCase::DeselectedEvent()
{
#if wxUSE_UIACTIONSIMULATOR
m_list->SetItemCount(1);
wxListCtrl* const list = m_list;
EventCounter selected(list, wxEVT_LIST_ITEM_SELECTED);
EventCounter deselected(list, wxEVT_LIST_ITEM_DESELECTED);
wxUIActionSimulator sim;
wxRect pos;
list->GetItemRect(0, pos);
//We move in slightly so we are not on the edge
wxPoint point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 10);
sim.MouseMove(point);
wxYield();
sim.MouseClick();
wxYield();
// We want a point within the listctrl but below any items
point = list->ClientToScreen(pos.GetPosition()) + wxPoint(10, 50);
sim.MouseMove(point);
wxYield();
sim.MouseClick();
wxYield();
CPPUNIT_ASSERT_EQUAL(1, selected.GetCount());
CPPUNIT_ASSERT_EQUAL(1, deselected.GetCount());
#endif
}
#endif // wxUSE_LISTCTRL

View File

@@ -0,0 +1,447 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/webtest.cpp
// Purpose: wxWebView unit test
// Author: Steven Lamerton
// Created: 2011-07-08
// Copyright: (c) 2011 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#if wxUSE_WEBVIEW && (wxUSE_WEBVIEW_WEBKIT || wxUSE_WEBVIEW_WEBKIT2 || wxUSE_WEBVIEW_IE)
#ifndef WX_PRECOMP
#include "wx/app.h"
#endif // WX_PRECOMP
#include "testableframe.h"
#include "wx/webview.h"
#include "asserthelper.h"
#if wxUSE_WEBVIEW_IE
#include "wx/msw/webview_ie.h"
#endif
#if wxUSE_WEBVIEW_WEBKIT2
#include "waitfor.h"
#endif
//Convenience macro
#define ENSURE_LOADED CHECK( m_loaded->WaitEvent() )
class WebViewTestCase
{
public:
WebViewTestCase()
: m_browser(wxWebView::New()),
m_loaded(new EventCounter(m_browser, wxEVT_WEBVIEW_LOADED))
{
#ifdef __WXMSW__
if (wxWebView::IsBackendAvailable(wxWebViewBackendEdge))
{
// The blank page does not have an empty title with edge
m_blankTitle = "about:blank";
// Edge does not support about: url use a different URL instead
m_alternateHistoryURL = "about:blank";
}
else
#endif
#if wxUSE_WEBVIEW_WEBKIT2
m_alternateHistoryURL = "about:srcdoc";
#else
m_alternateHistoryURL = "about:";
#endif
}
~WebViewTestCase()
{
delete m_loaded;
delete m_browser;
}
protected:
void LoadUrl(int times = 1)
{
//We alternate between urls as otherwise webkit merges them in the history
//we use about and about blank to avoid the need for a network connection
for(int i = 0; i < times; i++)
{
if(i % 2 == 1)
m_browser->LoadURL("about:blank");
else
m_browser->LoadURL(m_alternateHistoryURL);
ENSURE_LOADED;
}
}
void OnScriptResult(const wxWebViewEvent& evt)
{
m_asyncScriptResult = (evt.IsError()) ? 0 : 1;
m_asyncScriptString = evt.GetString();
}
void RunAsyncScript(const wxString& javascript)
{
m_browser->Bind(wxEVT_WEBVIEW_SCRIPT_RESULT, &WebViewTestCase::OnScriptResult, this);
m_asyncScriptResult = -1;
m_browser->RunScriptAsync(javascript);
while (m_asyncScriptResult == -1)
wxYield();
m_browser->Unbind(wxEVT_WEBVIEW_SCRIPT_RESULT, &WebViewTestCase::OnScriptResult, this);
}
wxWebView* const m_browser;
EventCounter* const m_loaded;
wxString m_blankTitle;
wxString m_alternateHistoryURL;
int m_asyncScriptResult;
wxString m_asyncScriptString;
};
TEST_CASE_METHOD(WebViewTestCase, "WebView", "[wxWebView]")
{
#if defined(__WXGTK__) && !defined(__WXGTK3__)
wxString value;
if ( !wxGetEnv("wxTEST_WEBVIEW_GTK2", &value) || value != "1" )
{
WARN("Skipping WebView tests known to fail with wxGTK 2, set "
"wxTEST_WEBVIEW_GTK2=1 to force running them.");
return;
}
#endif
m_browser -> Create(wxTheApp->GetTopWindow(), wxID_ANY);
ENSURE_LOADED;
SECTION("Title")
{
CHECK(m_browser->GetCurrentTitle() == "");
//Test title after loading raw html
m_browser->SetPage("<html><title>Title</title><body>Text</body></html>", "");
ENSURE_LOADED;
CHECK(m_browser->GetCurrentTitle() == "Title");
//Test title after loading a url, we yield to let events process
LoadUrl();
CHECK(m_browser->GetCurrentTitle() == m_blankTitle);
}
SECTION("URL")
{
CHECK(m_browser->GetCurrentURL() == "about:blank");
//After first loading about:blank the next in the sequence is about:
LoadUrl();
CHECK(m_browser->GetCurrentURL() == m_alternateHistoryURL);
}
SECTION("History")
{
LoadUrl(3);
CHECK(m_browser->CanGoBack());
CHECK(!m_browser->CanGoForward());
m_browser->GoBack();
ENSURE_LOADED;
CHECK(m_browser->CanGoBack());
CHECK(m_browser->CanGoForward());
m_browser->GoBack();
ENSURE_LOADED;
m_browser->GoBack();
ENSURE_LOADED;
//We should now be at the start of the history
CHECK(!m_browser->CanGoBack());
CHECK(m_browser->CanGoForward());
}
#if !wxUSE_WEBVIEW_WEBKIT2 && !defined(__WXOSX__)
SECTION("HistoryEnable")
{
LoadUrl();
m_browser->EnableHistory(false);
CHECK(!m_browser->CanGoForward());
CHECK(!m_browser->CanGoBack());
LoadUrl();
CHECK(!m_browser->CanGoForward());
CHECK(!m_browser->CanGoBack());
}
#endif
#if !wxUSE_WEBVIEW_WEBKIT2 && !defined(__WXOSX__)
SECTION("HistoryClear")
{
LoadUrl(2);
//Now we are in the 'middle' of the history
m_browser->GoBack();
ENSURE_LOADED;
CHECK(m_browser->CanGoForward());
CHECK(m_browser->CanGoBack());
m_browser->ClearHistory();
CHECK(!m_browser->CanGoForward());
CHECK(!m_browser->CanGoBack());
}
#endif
SECTION("HistoryList")
{
LoadUrl(2);
m_browser->GoBack();
ENSURE_LOADED;
CHECK(m_browser->GetBackwardHistory().size() == 1);
CHECK(m_browser->GetForwardHistory().size() == 1);
m_browser->LoadHistoryItem(m_browser->GetForwardHistory()[0]);
ENSURE_LOADED;
CHECK(!m_browser->CanGoForward());
CHECK(m_browser->GetBackwardHistory().size() == 2);
}
#if !defined(__WXOSX__) && (!defined(wxUSE_WEBVIEW_EDGE) || !wxUSE_WEBVIEW_EDGE)
SECTION("Editable")
{
CHECK(!m_browser->IsEditable());
m_browser->SetEditable(true);
CHECK(m_browser->IsEditable());
m_browser->SetEditable(false);
CHECK(!m_browser->IsEditable());
}
#endif
SECTION("Selection")
{
m_browser->SetPage("<html><body>Some <strong>strong</strong> text</body></html>", "");
ENSURE_LOADED;
CHECK(!m_browser->HasSelection());
m_browser->SelectAll();
#if wxUSE_WEBVIEW_WEBKIT2
// With WebKit SelectAll() sends a request to perform the selection to
// another process via proxy and there doesn't seem to be any way to
// wait until this request is actually handled, so loop here for some a
// bit before giving up. Avoid calling HasSelection() right away
// without wxYielding a bit because this seems to cause the extension
// to hang with webkit 2.40.0+.
YieldForAWhile();
#endif // wxUSE_WEBVIEW_WEBKIT2
CHECK(m_browser->HasSelection());
CHECK(m_browser->GetSelectedText() == "Some strong text");
#if !defined(__WXOSX__) && (!defined(wxUSE_WEBVIEW_EDGE) || !wxUSE_WEBVIEW_EDGE)
// The web engine doesn't necessarily represent the HTML in the same way as
// we used above, e.g. IE uses upper case for all the tags while WebKit
// under OS X inserts plenty of its own <span> tags, so don't test for
// equality and just check that the source contains things we'd expect it
// to.
const wxString selSource = m_browser->GetSelectedSource();
WX_ASSERT_MESSAGE
(
("Unexpected selection source: \"%s\"", selSource),
selSource.Lower().Matches("*some*<strong*strong</strong>*text*")
);
#endif // !defined(__WXOSX__)
m_browser->ClearSelection();
CHECK(!m_browser->HasSelection());
}
SECTION("Zoom")
{
if(m_browser->CanSetZoomType(wxWEBVIEW_ZOOM_TYPE_LAYOUT))
{
m_browser->SetZoomType(wxWEBVIEW_ZOOM_TYPE_LAYOUT);
CHECK(m_browser->GetZoomType() == wxWEBVIEW_ZOOM_TYPE_LAYOUT);
m_browser->SetZoom(wxWEBVIEW_ZOOM_TINY);
CHECK(m_browser->GetZoom() == wxWEBVIEW_ZOOM_TINY);
}
//Reset the zoom level
m_browser->SetZoom(wxWEBVIEW_ZOOM_MEDIUM);
if(m_browser->CanSetZoomType(wxWEBVIEW_ZOOM_TYPE_TEXT))
{
m_browser->SetZoomType(wxWEBVIEW_ZOOM_TYPE_TEXT);
CHECK(m_browser->GetZoomType() == wxWEBVIEW_ZOOM_TYPE_TEXT);
m_browser->SetZoom(wxWEBVIEW_ZOOM_TINY);
CHECK(m_browser->GetZoom() == wxWEBVIEW_ZOOM_TINY);
}
}
SECTION("RunScript")
{
m_browser->
SetPage("<html><head><script></script></head><body></body></html>", "");
ENSURE_LOADED;
wxString result;
#if wxUSE_WEBVIEW_IE && !wxUSE_WEBVIEW_EDGE
// Define a specialized scope guard ensuring that we reset the emulation
// level to its default value even if any asserts below fail.
class ResetEmulationLevel
{
public:
ResetEmulationLevel()
{
// Allow this to fail because it doesn't work in GitHub Actions
// environment, but the tests below still pass there.
if ( !wxWebViewIE::MSWSetModernEmulationLevel() )
{
WARN("Setting IE modern emulation level failed.");
m_reset = false;
}
else
{
m_reset = true;
}
}
void DoReset()
{
if ( m_reset )
{
m_reset = false;
if ( !wxWebViewIE::MSWSetModernEmulationLevel(false) )
{
WARN("Resetting IE modern emulation level failed.");
}
}
}
~ResetEmulationLevel()
{
DoReset();
}
private:
bool m_reset;
} resetEmulationLevel;
CHECK(m_browser->RunScript("function f(){var person = new Object();person.name = 'Bar'; \
person.lastName = 'Foo';return person;}f();", &result));
CHECK(result == "{\"name\":\"Bar\",\"lastName\":\"Foo\"}");
CHECK(m_browser->RunScript("function f(){ return [\"foo\", \"bar\"]; }f();", &result));
CHECK(result == "[\"foo\",\"bar\"]");
CHECK(m_browser->RunScript("function f(){var d = new Date('10/08/2017 21:30:40'); \
var tzoffset = d.getTimezoneOffset() * 60000; return new Date(d.getTime() - tzoffset);}f();",
&result));
CHECK(result == "\"2017-10-08T21:30:40.000Z\"");
resetEmulationLevel.DoReset();
#endif // wxUSE_WEBVIEW_IE
CHECK(m_browser->RunScript("document.write(\"Hello World!\");"));
CHECK(m_browser->GetPageText() == "Hello World!");
CHECK(m_browser->RunScript("function f(a){return a;}f('Hello World!');", &result));
CHECK(result == _("Hello World!"));
CHECK(m_browser->RunScript("function f(a){return a;}f('a\\\'aa\\n\\rb\\tb\\\\ccc\\\"ddd\\b\\fx');", &result));
CHECK(result == _("a\'aa\n\rb\tb\\ccc\"ddd\b\fx"));
CHECK(m_browser->RunScript("function f(a){return a;}f(123);", &result));
CHECK(wxAtoi(result) == 123);
CHECK(m_browser->
RunScript("function f(a){return a;}f(2.34);", &result));
double value;
result.ToDouble(&value);
CHECK(value == 2.34);
CHECK(m_browser->RunScript("function f(a){return a;}f(false);", &result));
CHECK(result == "false");
CHECK(m_browser->RunScript("function f(){var person = new Object();person.lastName = 'Bar'; \
person.name = 'Foo';return person;}f();", &result));
CHECK(result == "{\"lastName\":\"Bar\",\"name\":\"Foo\"}");
CHECK(m_browser->RunScript("function f(){ return [\"foo\", \"bar\"]; }f();", &result));
CHECK(result == "[\"foo\",\"bar\"]");
CHECK(m_browser->RunScript("function f(){var person = new Object();}f();", &result));
CHECK(result == "undefined");
CHECK(m_browser->RunScript("function f(){return null;}f();", &result));
CHECK(result == "null");
result = "";
CHECK(!m_browser->RunScript("int main() { return 0; }", &result));
CHECK(result.empty());
CHECK(m_browser->RunScript("function a() { return eval(\"function b() { \
return eval(\\\"function c() { return eval(\\\\\\\"function d() { \
return \\\\\\\\\\\\\\\"test\\\\\\\\\\\\\\\"; } d();\\\\\\\"); } \
c();\\\"); } b();\"); } a();", &result));
CHECK(result == "test");
CHECK(m_browser->RunScript("function f(a){return a;}f(\"This is a backslash: \\\\\");",
&result));
CHECK(result == "This is a backslash: \\");
CHECK(m_browser->RunScript("function f(){var d = new Date('10/08/2016 21:30:40'); \
var tzoffset = d.getTimezoneOffset() * 60000; return new Date(d.getTime() - tzoffset);}f();",
&result));
CHECK(result == "\"2016-10-08T21:30:40.000Z\"");
// Check for C++-style comments which used to be broken.
CHECK(m_browser->RunScript("function f() {\n"
" // A C++ style comment\n"
" return 17;\n"
"}f();", &result));
CHECK(result == "17");
// Check for errors too.
CHECK(!m_browser->RunScript("syntax(error"));
CHECK(!m_browser->RunScript("syntax(error", &result));
CHECK(!m_browser->RunScript("x.y.z"));
}
SECTION("RunScriptAsync")
{
#ifdef __WXMSW__
// IE doesn't support async script execution
if (!wxWebView::IsBackendAvailable(wxWebViewBackendEdge))
return;
#endif
RunAsyncScript("function f(a){return a;}f('Hello World!');");
CHECK(m_asyncScriptResult == 1);
CHECK(m_asyncScriptString == "Hello World!");
RunAsyncScript("int main() { return 0; }");
CHECK(m_asyncScriptResult == 0);
}
SECTION("SetPage")
{
m_browser->SetPage("<html><body>text</body></html>", "");
ENSURE_LOADED;
CHECK(m_browser->GetPageText() == "text");
m_browser->SetPage("<html><body>other text</body></html>", "");
ENSURE_LOADED;
CHECK(m_browser->GetPageText() == "other text");
}
}
#endif //wxUSE_WEBVIEW && (wxUSE_WEBVIEW_WEBKIT || wxUSE_WEBVIEW_WEBKIT2 || wxUSE_WEBVIEW_IE)

View File

@@ -0,0 +1,520 @@
///////////////////////////////////////////////////////////////////////////////
// Name: tests/controls/windowtest.cpp
// Purpose: wxWindow unit test
// Author: Steven Lamerton
// Created: 2010-07-10
// Copyright: (c) 2010 Steven Lamerton
///////////////////////////////////////////////////////////////////////////////
#include "testprec.h"
#ifndef WX_PRECOMP
#include "wx/app.h"
#include "wx/window.h"
#include "wx/button.h"
#include "wx/sizer.h"
#endif // WX_PRECOMP
#include "asserthelper.h"
#include "testableframe.h"
#include "testwindow.h"
#include "waitfor.h"
#include "wx/uiaction.h"
#include "wx/caret.h"
#include "wx/cshelp.h"
#include "wx/dcclient.h"
#include "wx/tooltip.h"
#include "wx/wupdlock.h"
#include <memory>
class WindowTestCase
{
public:
WindowTestCase()
: m_window(new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY))
{
#ifdef __WXGTK3__
// Without this, when running this test suite solo it succeeds,
// but not when running it together with the other tests !!
// Not needed when run under Xvfb display.
YieldForAWhile();
#endif
}
~WindowTestCase()
{
wxTheApp->GetTopWindow()->DestroyChildren();
}
protected:
wxWindow* const m_window;
wxDECLARE_NO_COPY_CLASS(WindowTestCase);
};
static void DoTestShowHideEvent(wxWindow* window)
{
EventCounter show(window, wxEVT_SHOW);
CHECK(window->IsShown());
window->Show(false);
CHECK(!window->IsShown());
window->Show();
CHECK(window->IsShown());
CHECK( show.GetCount() == 2 );
}
TEST_CASE_METHOD(WindowTestCase, "Window::ShowHideEvent", "[window]")
{
SECTION("Normal window")
{
DoTestShowHideEvent(m_window);
}
SECTION("Frozen window")
{
wxWindowUpdateLocker freeze(m_window->GetParent() );
REQUIRE( m_window->IsFrozen() );
DoTestShowHideEvent(m_window);
}
}
TEST_CASE_METHOD(WindowTestCase, "Window::KeyEvent", "[window]")
{
#if wxUSE_UIACTIONSIMULATOR
if ( !EnableUITests() )
return;
EventCounter keydown(m_window, wxEVT_KEY_DOWN);
EventCounter keyup(m_window, wxEVT_KEY_UP);
EventCounter keychar(m_window, wxEVT_CHAR);
wxUIActionSimulator sim;
m_window->SetFocus();
wxYield();
sim.Text("text");
sim.Char(WXK_SHIFT);
wxYield();
CHECK( keydown.GetCount() == 5 );
CHECK( keyup.GetCount() == 5 );
CHECK( keychar.GetCount() == 4 );
#endif
}
TEST_CASE_METHOD(WindowTestCase, "Window::FocusEvent", "[window]")
{
#ifndef __WXOSX__
if ( IsAutomaticTest() )
{
// Skip this test when running under buildbot, it fails there for
// unknown reason and this failure can't be reproduced locally.
return;
}
EventCounter setfocus(m_window, wxEVT_SET_FOCUS);
EventCounter killfocus(m_window, wxEVT_KILL_FOCUS);
m_window->SetFocus();
CHECK(setfocus.WaitEvent(500));
CHECK_FOCUS_IS( m_window );
wxButton* button = new wxButton(wxTheApp->GetTopWindow(), wxID_ANY);
button->SetFocus();
wxYield();
CHECK( killfocus.GetCount() == 1 );
CHECK(!m_window->HasFocus());
#endif
}
TEST_CASE_METHOD(WindowTestCase, "Window::Mouse", "[window]")
{
wxCursor cursor(wxCURSOR_HAND);
m_window->SetCursor(cursor);
CHECK(m_window->GetCursor().IsOk());
#if wxUSE_CARET
CHECK(!m_window->GetCaret());
wxCaret* caret = nullptr;
// Try creating the caret in two different, but normally equivalent, ways.
SECTION("Caret 1-step")
{
caret = new wxCaret(m_window, 16, 16);
}
SECTION("Caret 2-step")
{
caret = new wxCaret();
caret->Create(m_window, 16, 16);
}
m_window->SetCaret(caret);
CHECK(m_window->GetCaret()->IsOk());
#endif
m_window->CaptureMouse();
CHECK(m_window->HasCapture());
m_window->ReleaseMouse();
CHECK(!m_window->HasCapture());
}
TEST_CASE_METHOD(WindowTestCase, "Window::Properties", "[window]")
{
m_window->SetLabel("label");
CHECK( m_window->GetLabel() == "label" );
m_window->SetName("name");
CHECK( m_window->GetName() == "name" );
//As we used wxID_ANY we should have a negative id
CHECK(m_window->GetId() < 0);
m_window->SetId(wxID_HIGHEST + 10);
CHECK( m_window->GetId() == wxID_HIGHEST + 10 );
}
#if wxUSE_TOOLTIPS
TEST_CASE_METHOD(WindowTestCase, "Window::ToolTip", "[window]")
{
CHECK(!m_window->GetToolTip());
CHECK( m_window->GetToolTipText() == "" );
m_window->SetToolTip("text tip");
CHECK( m_window->GetToolTipText() == "text tip" );
m_window->UnsetToolTip();
CHECK(!m_window->GetToolTip());
CHECK( m_window->GetToolTipText() == "" );
wxToolTip* tip = new wxToolTip("other tip");
m_window->SetToolTip(tip);
CHECK( m_window->GetToolTip() == tip );
CHECK( m_window->GetToolTipText() == "other tip" );
}
#endif // wxUSE_TOOLTIPS
TEST_CASE_METHOD(WindowTestCase, "Window::Help", "[window]")
{
#if wxUSE_HELP
wxHelpProvider::Set(new wxSimpleHelpProvider());
CHECK( m_window->GetHelpText() == "" );
m_window->SetHelpText("helptext");
CHECK( m_window->GetHelpText() == "helptext" );
#endif
}
TEST_CASE_METHOD(WindowTestCase, "Window::Parent", "[window]")
{
CHECK( m_window->GetGrandParent() == static_cast<wxWindow*>(nullptr) );
CHECK( m_window->GetParent() == wxTheApp->GetTopWindow() );
}
TEST_CASE_METHOD(WindowTestCase, "Window::Siblings", "[window]")
{
CHECK( m_window->GetNextSibling() == static_cast<wxWindow*>(nullptr) );
CHECK( m_window->GetPrevSibling() == static_cast<wxWindow*>(nullptr) );
wxWindow* newwin = new wxWindow(wxTheApp->GetTopWindow(), wxID_ANY);
CHECK( m_window->GetNextSibling() == newwin );
CHECK( m_window->GetPrevSibling() == static_cast<wxWindow*>(nullptr) );
CHECK( newwin->GetNextSibling() == static_cast<wxWindow*>(nullptr) );
CHECK( newwin->GetPrevSibling() == m_window );
wxDELETE(newwin);
}
TEST_CASE_METHOD(WindowTestCase, "Window::Children", "[window]")
{
CHECK( m_window->GetChildren().GetCount() == 0 );
wxWindow* child1 = new wxWindow(m_window, wxID_ANY);
CHECK( m_window->GetChildren().GetCount() == 1 );
m_window->RemoveChild(child1);
CHECK( m_window->GetChildren().GetCount() == 0 );
child1->SetId(wxID_HIGHEST + 1);
child1->SetName("child1");
m_window->AddChild(child1);
CHECK( m_window->GetChildren().GetCount() == 1 );
CHECK( m_window->FindWindow(wxID_HIGHEST + 1) == child1 );
CHECK( m_window->FindWindow("child1") == child1 );
m_window->DestroyChildren();
CHECK( m_window->GetChildren().GetCount() == 0 );
}
TEST_CASE_METHOD(WindowTestCase, "Window::Focus", "[window]")
{
#ifndef __WXOSX__
CHECK(!m_window->HasFocus());
if ( m_window->AcceptsFocus() )
{
m_window->SetFocus();
CHECK_FOCUS_IS(m_window);
}
//Set the focus back to the main window
wxTheApp->GetTopWindow()->SetFocus();
if ( m_window->AcceptsFocusFromKeyboard() )
{
m_window->SetFocusFromKbd();
CHECK_FOCUS_IS(m_window);
}
#endif
}
TEST_CASE_METHOD(WindowTestCase, "Window::Positioning", "[window]")
{
//Some basic tests for consistency
int x, y;
m_window->GetPosition(&x, &y);
CHECK( m_window->GetPosition().x == x );
CHECK( m_window->GetPosition().y == y );
CHECK( m_window->GetRect().GetTopLeft() == m_window->GetPosition() );
m_window->GetScreenPosition(&x, &y);
CHECK( m_window->GetScreenPosition().x == x );
CHECK( m_window->GetScreenPosition().y == y );
CHECK( m_window->GetScreenRect().GetTopLeft() == m_window->GetScreenPosition() );
}
TEST_CASE_METHOD(WindowTestCase, "Window::PositioningBeyondShortLimit", "[window]")
{
#ifdef __WXMSW__
//Positioning under MSW is limited to short relative coordinates
//
//Test window creation beyond SHRT_MAX
int commonDim = 10;
wxWindow* w = new wxWindow(m_window, wxID_ANY,
wxPoint(0, SHRT_MAX + commonDim),
wxSize(commonDim, commonDim));
CHECK( w->GetPosition().y == SHRT_MAX + commonDim );
w->Move(0, 0);
//
//Test window moving beyond SHRT_MAX
w->Move(0, SHRT_MAX + commonDim);
CHECK( w->GetPosition().y == SHRT_MAX + commonDim );
//
//Test window moving below SHRT_MIN
w->Move(0, SHRT_MIN - commonDim);
CHECK( w->GetPosition().y == SHRT_MIN - commonDim );
//
//Test deferred move beyond SHRT_MAX
m_window->SetVirtualSize(-1, SHRT_MAX + 2 * commonDim);
wxWindow* bigWin = new wxWindow(m_window, wxID_ANY, wxDefaultPosition,
//size is also limited by SHRT_MAX
wxSize(commonDim, SHRT_MAX));
wxSizer *sizer = new wxBoxSizer(wxVERTICAL);
sizer->Add(bigWin);
sizer->AddSpacer(commonDim); //add some space to go beyond SHRT_MAX
sizer->Add(w);
m_window->SetSizer(sizer);
m_window->Layout();
CHECK( w->GetPosition().y == SHRT_MAX + commonDim );
#endif
}
TEST_CASE_METHOD(WindowTestCase, "Window::Show", "[window]")
{
CHECK(m_window->IsShown());
m_window->Hide();
CHECK(!m_window->IsShown());
m_window->Show();
CHECK(m_window->IsShown());
m_window->Show(false);
CHECK(!m_window->IsShown());
m_window->ShowWithEffect(wxSHOW_EFFECT_BLEND);
CHECK(m_window->IsShown());
m_window->HideWithEffect(wxSHOW_EFFECT_BLEND);
CHECK(!m_window->IsShown());
}
TEST_CASE_METHOD(WindowTestCase, "Window::Enable", "[window]")
{
CHECK(m_window->IsEnabled());
m_window->Disable();
CHECK(!m_window->IsEnabled());
m_window->Enable();
CHECK(m_window->IsEnabled());
m_window->Enable(false);
CHECK(!m_window->IsEnabled());
m_window->Enable();
wxWindow* const child = new wxWindow(m_window, wxID_ANY);
CHECK(child->IsEnabled());
CHECK(child->IsThisEnabled());
m_window->Disable();
CHECK(!child->IsEnabled());
CHECK(child->IsThisEnabled());
child->Disable();
CHECK(!child->IsEnabled());
CHECK(!child->IsThisEnabled());
m_window->Enable();
CHECK(!child->IsEnabled());
CHECK(!child->IsThisEnabled());
child->Enable();
CHECK(child->IsEnabled());
CHECK(child->IsThisEnabled());
}
TEST_CASE_METHOD(WindowTestCase, "Window::FindWindowBy", "[window]")
{
m_window->SetId(wxID_HIGHEST + 1);
m_window->SetName("name");
m_window->SetLabel("label");
CHECK( wxWindow::FindWindowById(wxID_HIGHEST + 1) == m_window );
CHECK( wxWindow::FindWindowByName("name") == m_window );
CHECK( wxWindow::FindWindowByLabel("label") == m_window );
CHECK( wxWindow::FindWindowById(wxID_HIGHEST + 3) == nullptr );
CHECK( wxWindow::FindWindowByName("noname") == nullptr );
CHECK( wxWindow::FindWindowByLabel("nolabel") == nullptr );
}
TEST_CASE_METHOD(WindowTestCase, "Window::SizerErrors", "[window][sizer][error]")
{
wxWindow* const child = new wxWindow(m_window, wxID_ANY);
std::unique_ptr<wxSizer> const sizer1(new wxBoxSizer(wxHORIZONTAL));
std::unique_ptr<wxSizer> const sizer2(new wxBoxSizer(wxHORIZONTAL));
REQUIRE_NOTHROW( sizer1->Add(child) );
#ifdef __WXDEBUG__
CHECK_THROWS_AS( sizer1->Add(child), TestAssertFailure );
CHECK_THROWS_AS( sizer2->Add(child), TestAssertFailure );
#else
CHECK_NOTHROW( sizer1->Add(child) );
CHECK_NOTHROW( sizer2->Add(child) );
#endif
CHECK_NOTHROW( sizer1->Detach(child) );
CHECK_NOTHROW( sizer2->Add(child) );
REQUIRE_NOTHROW( delete child );
}
TEST_CASE_METHOD(WindowTestCase, "Window::Refresh", "[window]")
{
wxWindow* const parent = m_window;
wxWindow* const child1 = new wxWindow(parent, wxID_ANY, wxPoint(10, 20), wxSize(80, 50));
wxWindow* const child2 = new wxWindow(parent, wxID_ANY, wxPoint(110, 20), wxSize(80, 50));
wxWindow* const child3 = new wxWindow(parent, wxID_ANY, wxPoint(210, 20), wxSize(80, 50));
m_window->SetSize(300, 100);
// to help see the windows when debugging
parent->SetBackgroundColour(*wxBLACK);
child1->SetBackgroundColour(*wxBLUE);
child2->SetBackgroundColour(*wxRED);
child3->SetBackgroundColour(*wxGREEN);
// Notice that using EventCounter here will give incorrect results,
// so we have to bind each window to a distinct event handler instead.
bool isParentPainted;
bool isChild1Painted;
bool isChild2Painted;
bool isChild3Painted;
const auto setFlagOnPaint = [](wxWindow* win, bool* flag)
{
win->Bind(wxEVT_PAINT, [=](wxPaintEvent&)
{
wxPaintDC dc(win);
*flag = true;
});
};
setFlagOnPaint(parent, &isParentPainted);
setFlagOnPaint(child1, &isChild1Painted);
setFlagOnPaint(child2, &isChild2Painted);
setFlagOnPaint(child3, &isChild3Painted);
// Prepare for the RefreshRect() call below
wxYield();
// Now initialize/reset the flags before calling RefreshRect()
isParentPainted =
isChild1Painted =
isChild2Painted =
isChild3Painted = false;
parent->RefreshRect(wxRect(150, 10, 300, 80));
WaitFor("parent repaint", [&]() { return isParentPainted; }, 100);
// child1 should be the only window not to receive the wxEVT_PAINT event
// because it does not intersect with the refreshed rectangle.
CHECK(isParentPainted == true);
CHECK(isChild1Painted == false);
CHECK(isChild2Painted == true);
CHECK(isChild3Painted == true);
}