def test_show_login():
    """
    The login dialog is displayed with a clean state.
    """
    mock_controller = mock.MagicMock()
    w = Window()
    w.setup(mock_controller)
    with mock.patch('securedrop_client.gui.main.LoginDialog') as mock_ld:
        w.show_login()
        mock_ld.assert_called_once_with(w)
    w.login_dialog.reset.assert_called_once_with()
    w.login_dialog.exec.assert_called_once_with()
def test_on_source_changed():
    """
    Ensure the event handler for when a source is changed calls the
    show_conversation_for method with the expected source object.
    """
    w = Window()
    w.main_view = mock.MagicMock()
    w.main_view.source_list.currentItem()
    mock_sw = w.main_view.source_list.itemWidget()
    w.show_conversation_for = mock.MagicMock()
    w.on_source_changed()
    w.show_conversation_for.assert_called_once_with(mock_sw.source)
示例#3
0
def test_logout(mocker):
    """
    Ensure the left pane updates to the logged out state.
    """
    w = Window()
    w.left_pane = mocker.MagicMock()
    w.top_pane = mocker.MagicMock()

    w.logout()

    w.left_pane.set_logged_out.assert_called_once_with()
    w.top_pane.disable_refresh.assert_called_once_with()
示例#4
0
def test_setup(mocker):
    """
    Ensure the passed in controller is referenced and the various views are
    instantiated as expected.
    """
    w = Window()
    mock_controller = mocker.MagicMock()
    w.show_login = mocker.MagicMock()
    w.top_pane = mocker.MagicMock()
    w.left_pane = mocker.MagicMock()
    w.main_view = mocker.MagicMock()

    w.setup(mock_controller)

    assert w.controller == mock_controller
    w.top_pane.setup.assert_called_once_with(mock_controller)
    w.left_pane.setup.assert_called_once_with(w, mock_controller)
    w.main_view.setup.assert_called_once_with(mock_controller)
    w.show_login.assert_called_once_with()
示例#5
0
def start_app(args, qt_args) -> None:
    """
    Create all the top-level assets for the application, set things up and
    run the application. Specific tasks include:

    - set up locale and language.
    - set up logging.
    - create an application object.
    - create a window for the app.
    - create an API connection to the SecureDrop proxy.
    - create a SqlAlchemy session to local storage.
    - configure the client (logic) object.
    - ensure the application is setup in the default safe starting state.
    """
    configure_locale_and_language()
    init(args.sdc_home)
    configure_logging(args.sdc_home)
    logging.info('Starting SecureDrop Client {}'.format(__version__))

    app = QApplication(qt_args)
    app.setApplicationName('SecureDrop Client')
    app.setDesktopFileName('org.freedomofthepress.securedrop.client')
    app.setApplicationVersion(__version__)
    app.setAttribute(Qt.AA_UseHighDpiPixmaps)

    prevent_second_instance(app, args.sdc_home)

    gui = Window()
    app.setWindowIcon(load_icon(gui.icon))
    app.setStyleSheet(load_css('sdclient.css'))

    engine = make_engine(args.sdc_home)
    Session = sessionmaker(bind=engine)
    session = Session()

    controller = Controller("http://localhost:8081/", gui, session,
                            args.sdc_home, not args.no_proxy)
    controller.setup()

    configure_signal_handlers(app)
    timer = QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)

    sys.exit(app.exec_())
示例#6
0
def test_hide_login(mocker):
    """
    Ensure the login dialog is closed and hidden.
    """
    w = Window()
    w.show_login = mocker.MagicMock()
    ld = mocker.MagicMock()
    w.login_dialog = ld

    w.hide_login()

    ld.accept.assert_called_once_with()
    assert w.login_dialog is None
示例#7
0
def test_init(mocker):
    """
    Ensure the Window instance is setup in the expected manner.
    """
    mock_li = mocker.MagicMock(return_value=load_icon('icon.png'))
    mock_lo = mocker.MagicMock(return_value=QHBoxLayout())
    mock_lo().addWidget = mocker.MagicMock()
    mocker.patch('securedrop_client.gui.main.load_icon', mock_li)
    mock_lp = mocker.patch('securedrop_client.gui.main.LeftPane')
    mock_mv = mocker.patch('securedrop_client.gui.main.MainView')
    mocker.patch('securedrop_client.gui.main.QHBoxLayout', mock_lo)
    mocker.patch('securedrop_client.gui.main.QMainWindow')

    w = Window()

    mock_li.assert_called_once_with(w.icon)
    mock_lp.assert_called_once_with()
    mock_mv.assert_called_once_with(w.main_pane)
    assert mock_lo().addWidget.call_count == 2
示例#8
0
def run():
    """
    Create all the top-level assets for the application, set things up and
    run the application. Specific tasks include:

    - set up logging.
    - create an application object.
    - create a window for the app.
    - create an API connection to the SecureDrop proxy.
    - create a SqlAlchemy session to local storage.
    - configure the client (logic) object.
    - ensure the application is setup in the default safe starting state.
    """
    configure_logging()
    logging.info('Starting SecureDrop Client {}'.format(__version__))

    app = QApplication(sys.argv)
    app.setApplicationName('SecureDrop Client')
    app.setDesktopFileName('org.freedomofthepress.securedrop.client')
    app.setApplicationVersion(__version__)
    app.setAttribute(Qt.AA_UseHighDpiPixmaps)

    gui = Window()
    app.setWindowIcon(load_icon(gui.icon))
    app.setStyleSheet(load_css('sdclient.css'))

    Session = sessionmaker(bind=engine)
    session = Session()

    client = Client("http://localhost:8081/", gui, session)
    client.setup()

    def signal_handler(*nargs) -> None:
        app.quit()

    for sig in [signal.SIGINT, signal.SIGTERM]:
        signal.signal(sig, signal_handler)
    timer = QTimer()
    timer.start(500)
    timer.timeout.connect(lambda: None)

    sys.exit(app.exec_())
示例#9
0
def modal_dialog(mocker, homedir):
    app = QApplication([])
    gui = Window()
    gui.show()
    controller = Controller("http://localhost", gui, mocker.MagicMock(), homedir, proxy=False)
    controller.qubes = False
    gui.setup(controller)
    gui.login_dialog.close()
    app.setActiveWindow(gui)
    dialog = ModalDialog()

    yield dialog

    dialog.close()
    app.exit()
示例#10
0
def test_init(mocker):
    """
    Ensure the Window instance is setup in the expected manner.
    """
    mock_li = mocker.MagicMock(return_value=load_icon("icon.png"))
    mock_lo = mocker.MagicMock(return_value=QHBoxLayout())
    mock_lo().addWidget = mocker.MagicMock()
    mocker.patch("securedrop_client.gui.main.load_icon", mock_li)
    mock_lp = mocker.patch("securedrop_client.gui.main.LeftPane")
    mock_mv = mocker.patch("securedrop_client.gui.main.MainView")
    mocker.patch("securedrop_client.gui.main.QHBoxLayout", mock_lo)
    mocker.patch("securedrop_client.gui.main.QMainWindow")
    mocker.patch("securedrop_client.gui.main.Window.setStyleSheet")
    load_css = mocker.patch("securedrop_client.gui.main.load_css")

    w = Window()

    mock_li.assert_called_once_with(w.icon)
    mock_lp.assert_called_once_with()
    mock_mv.assert_called_once_with(w.main_pane)
    assert mock_lo().addWidget.call_count == 2
    load_css.assert_called_once_with("sdclient.css")
def test_conversation_for():
    """
    Test that the source collection is displayed in the conversation view.
    """
    w = Window()
    w.controller = mock.MagicMock()
    w.main_view = mock.MagicMock()
    mock_conview = mock.MagicMock()
    mock_source = mock.MagicMock()
    mock_source.journalistic_designation = 'Testy McTestface'
    mock_file = mock.MagicMock()
    mock_file.filename = '1-my-source-doc.gpg'
    mock_message = mock.MagicMock()
    mock_message.filename = '2-my-source-msg.gpg'
    mock_reply = mock.MagicMock()
    mock_reply.filename = '3-my-source-reply.gpg'
    mock_source.collection = [mock_file, mock_message, mock_reply]
    with mock.patch('securedrop_client.gui.main.ConversationView',
                    mock_conview):
        w.show_conversation_for(mock_source)
    conv = mock_conview()
    assert conv.add_message.call_count > 0
    assert conv.add_reply.call_count > 0
    assert conv.add_file.call_count > 0