#include <QtTest>
#include <QSignalSpy>
#include <QCoreApplication>
#include <QPushButton>
#include <QGridLayout>
#include <QDialog>
#include <QMessageBox>
#include <ctime>
#include <fstream>
#include "dialog.h"

// Test the handleButtonClick function
void testHandleButtonClick() {
    QPushButton* button = new QPushButton();
    button->setEnabled(true);

    // Simulate a button click
    handleButtonClick(0, 0, button);

    // After clicking, the button text should be "X"
    QCOMPARE(button->text(), QString("X"));
    // After clicking, the button should be disabled
    QCOMPARE(button->isEnabled(), false);
}

// Test the checkWin function
void testCheckWin() {
    grid[0][0] = grid[0][1] = grid[0][2] = Player::X;
    QCOMPARE(checkWin(Player::X), true);

    // Reset the grid for further tests
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            grid[i][j] = Player::None;
        }
    }

    grid[0][0] = grid[1][0] = grid[2][0] = Player::O;
    QCOMPARE(checkWin(Player::O), true);
}

// Test the checkTie function
void testCheckTie() {
    // Fill the grid with X and O alternatively
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 3; ++j) {
            grid[i][j] = (i + j) % 2 == 0 ? Player::X : Player::O;
        }
    }
    // The grid is full, so it should be a tie
    QCOMPARE(checkTie(), true);
}

// Test the saveGame function
void testSaveGame() {
    // Initialize gameMoves
    gameMoves = {"X00", "O01", "X02", "O10", "X11"};

    // Call the saveGame function
    saveGame();

    // Check if the game history file is created and contains the correct data
    std::ifstream file(getPath("/history.txt").toStdString());
    std::string line;
    std::getline(file, line);
    QVERIFY(!line.empty());
    file.close();
}

// Test the execution of the game
void testExecuteGame() {
    // Initialize a Dialog object
    Dialog dialog;
    dialog.setModal(true);

    // Simulate clicking the start game button
    dialog.on_pushButton_clicked();

    // Find all buttons in the layout
    QGridLayout* layout = dialog.findChild<QGridLayout*>("gridLayout");
    QVERIFY(layout != nullptr);

    QList<QPushButton*> buttons = dialog.findChildren<QPushButton*>();
    QVERIFY(buttons.size() == 9); // 3x3 grid

    // Simulate clicking all buttons
    for (auto button : buttons) {
        QSignalSpy spy(button, &QPushButton::clicked);
        QVERIFY(spy.isValid());
        button->click();
        QVERIFY(spy.wait());
    }
}

// Test the Dialog constructor
void testDialogConstructor() {
    Dialog dialog(nullptr, 1, "Player 1", "Player 2");

    // Check if the button text is set correctly
    QCOMPARE(dialog.findChild<QPushButton*>("pushButton_display1")->text(), QString("Player 1's history"));
    QCOMPARE(dialog.findChild<QPushButton*>("pushButton_display2")->text(), QString("Player 2's history"));
}

// Test the Dialog pushButton_display1_clicked slot
void testPushButtonDisplay1Clicked() {
    Dialog dialog(nullptr, 1, "Player 1", "Player 2");

    // Simulate clicking the display1 button
    dialog.on_pushButton_display1_clicked();

    // Check if the gamesList dialog is opened
    QVERIFY(dialog.games != nullptr);
}

// Test the Dialog pushButton_display2_clicked slot
void testPushButtonDisplay2Clicked() {
    Dialog dialog(nullptr, 2, "Player 1", "Player 2");

    // Simulate clicking the display2 button
    dialog.on_pushButton_display2_clicked();

    // Check if the gamesList dialog is opened
    QVERIFY(dialog.games != nullptr);
}

// Define a custom test main to avoid conflicts with Qt framework
int main(int argc, char *argv[]) {
    // Initialize Qt application
    QApplication app(argc, argv);

    // Run the tests
    testHandleButtonClick();
    testCheckWin();
    testCheckTie();
    testSaveGame();
    testExecuteGame();
    testDialogConstructor();
    testPushButtonDisplay1Clicked();
    testPushButtonDisplay2Clicked();

    // Close the application
    return QTest::qExec(&app, argc, argv);
}
 
by

C++ Online Compiler

Write, Run & Share C++ code online using OneCompiler's C++ online compiler for free. It's one of the robust, feature-rich online compilers for C++ language, running on the latest version 17. Getting started with the OneCompiler's C++ compiler is simple and pretty fast. The editor shows sample boilerplate code when you choose language as C++ and start coding!

Read inputs from stdin

OneCompiler's C++ online compiler supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample program which takes name as input and print your name with hello.

#include <iostream>
#include <string>
using namespace std;

int main() 
{
    string name;
    cout << "Enter name:";
    getline (cin, name);
    cout << "Hello " << name;
    return 0;
}

About C++

C++ is a widely used middle-level programming language.

  • Supports different platforms like Windows, various Linux flavours, MacOS etc
  • C++ supports OOPS concepts like Inheritance, Polymorphism, Encapsulation and Abstraction.
  • Case-sensitive
  • C++ is a compiler based language
  • C++ supports structured programming language
  • C++ provides alot of inbuilt functions and also supports dynamic memory allocation.
  • Like C, C++ also allows you to play with memory using Pointers.

Syntax help

Loops

1. If-Else:

When ever you want to perform a set of operations based on a condition If-Else is used.

if(conditional-expression) {
   //code
}
else {
   //code
}

You can also use if-else for nested Ifs and If-Else-If ladder when multiple conditions are to be performed on a single variable.

2. Switch:

Switch is an alternative to If-Else-If ladder.

switch(conditional-expression){    
case value1:    
 // code    
 break;  // optional  
case value2:    
 // code    
 break;  // optional  
......    
    
default:     
 code to be executed when all the above cases are not matched;    
} 

3. For:

For loop is used to iterate a set of statements based on a condition.

for(Initialization; Condition; Increment/decrement){  
  //code  
} 

4. While:

While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.

while (condition) {  
// code 
}  

5. Do-While:

Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.

do {  
 // code 
} while (condition); 

Functions

Function is a sub-routine which contains set of statements. Usually functions are written when multiple calls are required to same set of statements which increases re-usuability and modularity. Function gets run only when it is called.

How to declare a Function:

return_type function_name(parameters);

How to call a Function:

function_name (parameters)

How to define a Function:

return_type function_name(parameters) {  
 // code
}