def setUp(self):
     self.viewmodel = CalculateAreaViewModel()
class TestCalculateAreaViewModel(unittest.TestCase):
    def setUp(self):
        self.viewmodel = CalculateAreaViewModel()

    def test_calc_button_disabled_by_default(self):
        self.assertEqual("disabled", self.viewmodel.get_calc_button_state())

    def test_calc_button_enabled_with_values_for_cone(self):
        self.viewmodel.set_figure_type("CONE")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1.0")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("2.2")
        self.assertEqual("normal", self.viewmodel.get_calc_button_state())

    def test_calc_button_enabled_with_values_for_cube(self):
        self.viewmodel.set_figure_type("CUBE")
        self.viewmodel.set_a("1")
        self.viewmodel.set_r("abc")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("ghi")
        self.assertEqual("normal", self.viewmodel.get_calc_button_state())

    def test_calc_button_enabled_with_values_for_sphere(self):
        self.viewmodel.set_figure_type("SPHERE")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("ghi")
        self.assertEqual("normal", self.viewmodel.get_calc_button_state())

    def test_calc_button_enabled_with_values_for_cylinder(self):
        self.viewmodel.set_figure_type("CYLINDER")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1")
        self.viewmodel.set_h("3")
        self.viewmodel.set_l("def")
        self.assertEqual("normal", self.viewmodel.get_calc_button_state())

    def test_calc_button_disabled_after_incorrect_value_input(self):
        self.viewmodel.set_figure_type("CYLINDER")
        self.viewmodel.set_r("1")
        self.viewmodel.set_h("3")
        self.viewmodel.set_h("hello, i'm incorrect value")
        self.assertEqual("disabled", self.viewmodel.get_calc_button_state())

    def test_calc_button_disabled_after_changed_figure_type(self):
        self.viewmodel.set_figure_type("CYLINDER")
        self.viewmodel.set_r("1")
        self.viewmodel.set_h("3")
        self.viewmodel.set_figure_type("CUBE")
        self.assertEqual("disabled", self.viewmodel.get_calc_button_state())

    def test_message_empty_with_valid_r_l_cone(self):
        self.viewmodel.set_figure_type("CONE")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1.0")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("2.2")
        self.assertEqual("", self.viewmodel.get_message())

    def test_message_empty_with_valid_a_cube(self):
        self.viewmodel.set_figure_type("CUBE")
        self.viewmodel.set_a("1")
        self.viewmodel.set_r("abc")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("ghi")
        self.assertEqual("", self.viewmodel.get_message())

    def test_message_empty_with_valid_r_sphere(self):
        self.viewmodel.set_figure_type("SPHERE")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("ghi")
        self.assertEqual("", self.viewmodel.get_message())

    def test_message_empty_with_valid_r_h_cylinder(self):
        self.viewmodel.set_figure_type("CYLINDER")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1")
        self.viewmodel.set_h("3")
        self.viewmodel.set_l("def")
        self.assertEqual("", self.viewmodel.get_message())

    def test_correct_message_with_invalid_r_l_cone(self):
        self.viewmodel.set_figure_type("CONE")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1.0 privet")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("2.2")
        self.assertEqual("r or l has incorrect value",
                         self.viewmodel.get_message())

    def test_correct_message_with_invalid_a_cube(self):
        self.viewmodel.set_figure_type("CUBE")
        self.viewmodel.set_a("1b")
        self.viewmodel.set_r("abc")
        self.viewmodel.set_h("7")
        self.viewmodel.set_l("ghi")
        self.assertEqual("a has incorrect value", self.viewmodel.get_message())

    def test_correct_message_with_invalid_r_sphere(self):
        self.viewmodel.set_figure_type("SPHERE")
        self.viewmodel.set_a("5")
        self.viewmodel.set_r("1a")
        self.viewmodel.set_h("def")
        self.viewmodel.set_l("ghi")
        self.assertEqual("r has incorrect value", self.viewmodel.get_message())

    def test_correct_message_with_invalid_r_h_cylinder(self):
        self.viewmodel.set_figure_type("CYLINDER")
        self.viewmodel.set_a("abc")
        self.viewmodel.set_r("1a")
        self.viewmodel.set_h("3")
        self.viewmodel.set_l("def")
        self.assertEqual("r or h has incorrect value",
                         self.viewmodel.get_message())

    def test_check_area_with_valid_r_l_cone(self):
        self.viewmodel.set_figure_type("CONE")
        self.viewmodel.set_r("2.3")
        self.viewmodel.set_l("3.8")
        self.viewmodel.calculate()
        self.assertEqual("44.077", self.viewmodel.get_area())

    def test_check_area_with_valid_a_cube(self):
        self.viewmodel.set_figure_type("CUBE")
        self.viewmodel.set_a("5.9")
        self.viewmodel.calculate()
        self.assertEqual("208.86", self.viewmodel.get_area())

    def test_check_area_with_valid_r_sphere(self):
        self.viewmodel.set_figure_type("SPHERE")
        self.viewmodel.set_r("2.3")
        self.viewmodel.calculate()
        self.assertEqual("66.476", self.viewmodel.get_area())

    def test_check_area_with_valid_r_h_cylinder(self):
        self.viewmodel.set_figure_type("CYLINDER")
        self.viewmodel.set_r("2.3")
        self.viewmodel.set_h("4.2")
        self.viewmodel.calculate()
        self.assertEqual("93.934", self.viewmodel.get_area())
class TestViewModelFakeLogging(unittest.TestCase):
    def setUp(self):
        self.view_model = CalculateAreaViewModel(FakeLogger())

    def test_logging_init(self):
        self.assertEqual('Starting...',
                         self.view_model.logger.get_last_message())

    def test_logging_changing_side(self):
        self.view_model.set_a('1')
        self.assertEqual('Setting the side to 1',
                         self.view_model.logger.get_last_message())

    def test_logging_changing_radius(self):
        self.view_model.set_h('2')
        self.assertEqual('Setting the height to 2',
                         self.view_model.logger.get_last_message())

    def test_logging_changing_height(self):
        self.view_model.set_r('3')
        self.assertEqual('Setting the radius to 3',
                         self.view_model.logger.get_last_message())

    def test_logging_changing_length_of_reference(self):
        self.view_model.set_l('4')
        self.assertEqual('Setting the length of reference to 4',
                         self.view_model.logger.get_last_message())

    def test_logging_changing_figure_type(self):
        self.view_model.set_figure_type("CUBE")
        self.assertEqual('Setting figure type to CUBE',
                         self.view_model.logger.get_last_message())

    def test_logging_calculating_area(self):
        expected_messages = [
            'Button clicked', 'Selected figure type to CYLINDER',
            'Result: 93.934'
        ]

        self.view_model.set_r("2.3")
        self.view_model.set_h("4.2")
        self.view_model.set_figure_type("CYLINDER")
        self.view_model.calculate()

        self.assertEqual(expected_messages,
                         self.view_model.logger.get_log_messages()[-3:])
 def setUp(self):
     self.view_model = CalculateAreaViewModel(RealLogger())
class GUIView(ttk.Frame):
    default_sticky = tkinter.W + tkinter.E + tkinter.N + tkinter.S

    viewmodel = CalculateAreaViewModel()

    def __init__(self):
        ttk.Frame.__init__(self)
        self.master.title("Figure area calculator")
        self.master.geometry('200x150')
        self.master.resizable(width=False, height=False)

        self.lbl_figure_type = ttk.Label(text="Figure type:")

        self.cmb_figure_types = ttk.Combobox(
            values=["CONE", "CUBE", "SPHERE", "CYLINDER"],
            state="readonly", width=10)
        self.cmb_figure_types.current(0)

        self.lbl_a = ttk.Label(text="a =")
        self.txt_a = tkinter.Text(height=1, width=8)

        self.lbl_r = ttk.Label(text="r =")
        self.txt_r = tkinter.Text(height=1, width=8)

        self.lbl_h = ttk.Label(text="h =")
        self.txt_h = tkinter.Text(height=1, width=8)

        self.lbl_l = ttk.Label(text="l =")
        self.txt_l = tkinter.Text(height=1, width=8)

        self.btn_calculate = ttk.Button(text='Calculate area')
        self.lbl_result = ttk.Label(text="result", relief="sunken", width=18)

        self.lbl_message = ttk.Label(text="Info message", relief="sunken", width=30)

        self.mvvm_bind_events()
        self.set_weight_to_grid()
        self.mvvm_back_bind()

    def set_weight_to_grid(self):
        self.lbl_figure_type.grid(row=0, column=0)
        self.cmb_figure_types.grid(row=0, column=1)

        self.lbl_a.grid(row=1, column=0)
        self.lbl_r.grid(row=2, column=0)
        self.lbl_h.grid(row=3, column=0)
        self.lbl_l.grid(row=4, column=0)

        self.txt_a.grid(row=1, column=1)
        self.txt_r.grid(row=2, column=1)
        self.txt_h.grid(row=3, column=1)
        self.txt_l.grid(row=4, column=1)

        self.btn_calculate.grid(row=5, column=0)
        self.lbl_result.grid(row=5, column=1)

        self.lbl_message.grid(row=6, column=0, columnspan=2, sticky=tkinter.W + tkinter.N)

    def mvvm_bind_events(self):
        self.txt_a.bind('<KeyRelease>', self.txt_a_changed)
        self.txt_r.bind('<KeyRelease>', self.txt_r_changed)
        self.txt_h.bind('<KeyRelease>', self.txt_h_changed)
        self.txt_l.bind('<KeyRelease>', self.txt_l_changed)
        self.cmb_figure_types.bind('<<ComboboxSelected>>', self.figure_type_changed)
        self.btn_calculate.bind('<Button-1>', self.calculate_clicked)

    def mvvm_bind(self):
        self.viewmodel.set_a(self.txt_a.get("1.0", tkinter.END))
        self.viewmodel.set_r(self.txt_r.get("1.0", tkinter.END))
        self.viewmodel.set_h(self.txt_h.get("1.0", tkinter.END))
        self.viewmodel.set_l(self.txt_l.get("1.0", tkinter.END))
        self.viewmodel.set_figure_type(self.cmb_figure_types.get())

    def mvvm_back_bind(self):
        self.btn_calculate.config(state=self.viewmodel.get_calc_button_state())
        self.lbl_message.config(text=self.viewmodel.get_message())
        self.lbl_result.config(text=self.viewmodel.get_area())

    def txt_a_changed(self, event):
        self.mvvm_bind()
        self.mvvm_back_bind()

    def txt_r_changed(self, event):
        self.mvvm_bind()
        self.mvvm_back_bind()

    def txt_h_changed(self, event):
        self.mvvm_bind()
        self.mvvm_back_bind()

    def txt_l_changed(self, event):
        self.mvvm_bind()
        self.mvvm_back_bind()

    def figure_type_changed(self, event):
        self.mvvm_bind()
        self.mvvm_back_bind()

    def calculate_clicked(self, event):
        self.mvvm_bind()
        self.viewmodel.calculate()
        self.mvvm_back_bind()