File indexing completed on 2024-04-28 07:51:21
0001 /****************************************************************************** 0002 * KBlocks, a falling blocks game by KDE * 0003 * SPDX-FileCopyrightText: 2009-2021 Julian Helfferich <julian.helfferich@mailbox.org> * 0004 * * 0005 * SPDX-License-Identifier: GPL-2.0-or-later 0006 ******************************************************************************/ 0007 #include <memory> 0008 0009 #include <QTest> 0010 0011 #include "Testing/MockGraphics.h" 0012 #include "Testing/MockSingleGame.h" 0013 #include "Testing/MockSound.h" 0014 #include "Testing/MockSvgItem.h" 0015 0016 #include "Testing/TestingKBlocksItemGroup.h" 0017 0018 class testKBlocksItemGroup : public QObject 0019 { 0020 Q_OBJECT 0021 private Q_SLOTS: 0022 void refreshPositionShouldSetCorrectPositions(); 0023 void refreshPositionShouldClearCache(); 0024 void updateGameShouldProcessGameActionsOnGameOver(); 0025 void updateGameShouldRefreshItemsOnGameOver(); 0026 void stopGameShouldProcessRemainingGameActions(); 0027 }; 0028 0029 void testKBlocksItemGroup::refreshPositionShouldSetCorrectPositions() 0030 { 0031 /** 0032 * When refreshPosition is called, the positions of the SVG items 0033 * in the prepare area and the playing field are updated. The new 0034 * positions are determined from the (possibly updated) layout. 0035 */ 0036 MockSingleGame singleGame; 0037 MockGraphics graphics; 0038 graphics.m_PreviewArea_CenterPoint_X = 1; 0039 graphics.m_PreviewArea_CenterPoint_Y = 1; 0040 graphics.m_Block_Size = 1; 0041 graphics.m_PlayArea_NumberOfBlocks_X = 2; 0042 graphics.m_PlayArea_NumberOfBlocks_Y = 2; 0043 graphics.m_PlayArea_OffsetPoint_X = 1; 0044 graphics.m_PlayArea_OffsetPoint_Y = 1; 0045 MockSound sound; 0046 TestingKBlocksItemGroup itemGroup(0, &singleGame, &graphics, &sound); 0047 0048 graphics.m_PreviewArea_CenterPoint_X = 30; 0049 graphics.m_PreviewArea_CenterPoint_Y = 50; 0050 graphics.m_Block_Size = 12; 0051 graphics.m_PlayArea_OffsetPoint_X = 10; 0052 graphics.m_PlayArea_OffsetPoint_Y = 15; 0053 0054 itemGroup.refreshPosition(); 0055 0056 std::vector<QPointF> expectedPreparePositions{ 0057 { 0, 20}, 0058 {12, 20}, 0059 {24, 20}, 0060 {36, 20}, 0061 {48, 20}, 0062 { 0, 32}, 0063 {12, 32}, 0064 {24, 32}, 0065 {36, 32} 0066 }; 0067 0068 for (size_t i = 0; i < expectedPreparePositions.size(); ++i) { 0069 auto *prepareCell = itemGroup.getPrepareCell(i); 0070 QVERIFY(prepareCell != nullptr); 0071 QCOMPARE(prepareCell->pos(), expectedPreparePositions.at(i)); 0072 } 0073 0074 std::vector<QPointF> expectedFreezePositions{ 0075 {10, 15}, 0076 {22, 15}, 0077 {10, 27}, 0078 {22, 27} 0079 }; 0080 0081 for (size_t i = 0; i < expectedFreezePositions.size(); ++i) { 0082 auto *freezeCell = itemGroup.getFreezeCell(i); 0083 QVERIFY(freezeCell != nullptr); 0084 QCOMPARE(freezeCell->pos(), expectedFreezePositions.at(i)); 0085 } 0086 } 0087 0088 void testKBlocksItemGroup::refreshPositionShouldClearCache() 0089 { 0090 /** 0091 * The positions are refreshed when the layout changes. Then, also 0092 * the cache should be cleared to ensure that the graphics for each 0093 * item is updated. 0094 * 0095 * See bug 380474 0096 */ 0097 MockSingleGame singleGame; 0098 MockGraphics graphics; 0099 MockSound sound; 0100 TestingKBlocksItemGroup itemGroup(0, &singleGame, &graphics, &sound); 0101 0102 itemGroup.replacePrepareCell(0, new MockSvgItem()); 0103 itemGroup.replaceFreezeCell(0, new MockSvgItem()); 0104 0105 auto *prepareCellBefore = dynamic_cast<MockSvgItem*>( 0106 itemGroup.getPrepareCell(0) 0107 ); 0108 QVERIFY(prepareCellBefore != nullptr); 0109 QCOMPARE(prepareCellBefore->clearCacheCalled, false); 0110 0111 auto *freezeCellBefore = dynamic_cast<MockSvgItem*>( 0112 itemGroup.getFreezeCell(0) 0113 ); 0114 QVERIFY(freezeCellBefore != nullptr); 0115 QCOMPARE(freezeCellBefore->clearCacheCalled, false); 0116 0117 itemGroup.refreshPosition(); 0118 0119 auto *prepareCellAfter = dynamic_cast<MockSvgItem*>( 0120 itemGroup.getPrepareCell(0) 0121 ); 0122 QVERIFY(prepareCellAfter != nullptr); 0123 QCOMPARE(prepareCellAfter->clearCacheCalled, true); 0124 0125 auto *freezeCellAfter = dynamic_cast<MockSvgItem*>( 0126 itemGroup.getFreezeCell(0) 0127 ); 0128 QVERIFY(freezeCellAfter != nullptr); 0129 QCOMPARE(freezeCellAfter->clearCacheCalled, true); 0130 } 0131 0132 0133 void testKBlocksItemGroup::updateGameShouldProcessGameActionsOnGameOver() 0134 { 0135 /** 0136 * When updateGame is called, updateLayout should be called even 0137 * when the game is over. Otherwise, some game actions are not 0138 * processed and the play area does not show where the last item 0139 * has moved, causing the game to be over. 0140 * 0141 * See bug 407244 0142 */ 0143 std::unique_ptr<SingleGameInterface> pSingleGame( new MockSingleGame() ); 0144 MockSingleGame *mock = dynamic_cast<MockSingleGame*>(pSingleGame.get()); 0145 mock->updateGameReturnValue = 1; 0146 0147 std::unique_ptr<GraphicsInterface> pGraphics( new MockGraphics() ); 0148 std::unique_ptr<SoundInterface> pSound( new MockSound() ); 0149 TestingKBlocksItemGroup itemGroup(0, pSingleGame.get(), pGraphics.get(), pSound.get() ); 0150 0151 itemGroup.callUpdateGame(); 0152 0153 QCOMPARE( mock->numberOfPickGameActionCalls, 1 ); 0154 } 0155 0156 void testKBlocksItemGroup::updateGameShouldRefreshItemsOnGameOver() 0157 { 0158 /** 0159 * When updateGame is called, the final piece might just have been 0160 * placed, causing the game to be over. If refreshItems() is not 0161 * called, the final piece will be invisible. The correct behavior 0162 * is to fully display the final piece, making it clear how and 0163 * where it conflicted with the pieces on the field. 0164 */ 0165 std::unique_ptr<SingleGameInterface> pSingleGame( new MockSingleGame() ); 0166 std::unique_ptr<GraphicsInterface> pGraphics( new MockGraphics() ); 0167 std::unique_ptr<SoundInterface> pSound( new MockSound() ); 0168 TestingKBlocksItemGroup itemGroup(0, pSingleGame.get(), pGraphics.get(), pSound.get() ); 0169 0170 MockSvgItem *svgItem = new MockSvgItem(); 0171 itemGroup.replaceFreezeCell(0, svgItem); 0172 0173 itemGroup.callUpdateGame(); 0174 0175 QVERIFY(svgItem->updateSelfCalled); 0176 } 0177 0178 0179 void testKBlocksItemGroup::stopGameShouldProcessRemainingGameActions() 0180 { 0181 /** 0182 * When the game is stopped (on game over), updateLayout needs to be 0183 * called. Otherwise, the play area is updated only after highscore 0184 * has been shown. 0185 * 0186 * See bug 407244 0187 */ 0188 std::unique_ptr<SingleGameInterface> pSingleGame( new MockSingleGame() ); 0189 std::unique_ptr<GraphicsInterface> pGraphics( new MockGraphics() ); 0190 std::unique_ptr<SoundInterface> pSound( new MockSound() ); 0191 KBlocksItemGroup itemGroup(0, pSingleGame.get(), pGraphics.get(), pSound.get() ); 0192 0193 itemGroup.stopGame(); 0194 0195 MockSingleGame *mock = dynamic_cast<MockSingleGame*>(pSingleGame.get()); 0196 QCOMPARE( mock->numberOfPickGameActionCalls, 1 ); 0197 } 0198 0199 0200 QTEST_MAIN(testKBlocksItemGroup) 0201 0202 #include "test_KBlocksItemGroup.moc"