Beispiel #1
0
def test_card_id_input_arg_must_be_integer(init_db):
    """
  get_card_by_id() takes in a card_id input argument, that must be integer.
  """
    card_obj = knards.Card()
    card_id = api.create_card(card_obj, init_db)

    result = api.get_card_by_id('1', init_db)
    assert result is None
def test_markers_arg_must_be_a_list_of_strings(init_db):
    """
  get_last_card() takes in an optional argument, markers, that must be a list
  of strings.
  """
    card_obj1 = knards.Card()
    api.create_card(card_obj1, init_db)

    result = api.get_last_card(markers=111, db_path=init_db)
    assert result is None

    result = api.get_last_card(markers='python', db_path=init_db)
    assert result is None

    result = api.get_last_card(markers=['python', 111], db_path=init_db)
    assert result is None

    result = api.get_last_card(markers=[], db_path=init_db)
    assert result.id == 1
def test_markers_arg_must_be_a_list_of_strings(init_db):
  """
  One of the arguments delete_card() takes in is markers, which must be a list
  of strings.
  """
  card_obj = knards.Card()
  api.create_card(card_obj, init_db)

  result = api.delete_card(markers='python', db_path=init_db)
  assert result is False

  result = api.delete_card(markers=1, db_path=init_db)
  assert result is False

  result = api.delete_card(markers=[1, 2, 3], db_path=init_db)
  assert result is False

  result = api.delete_card(markers=['python'], db_path=init_db)
  assert result is True
Beispiel #4
0
def test_returns_object_of_proper_type_and_has_id_set(init_db):
    """
  get_card_by_id() is expected to return an object of type knards.Card with
  the proper id set (one it was stored with)
  """
    card_obj = knards.Card()
    card_id = api.create_card(card_obj, init_db)
    result = api.get_card_by_id(card_id, init_db)

    assert isinstance(result, knards.Card)
    assert result.id == card_id
Beispiel #5
0
def test_if_both_id_and_markers_are_specified_ignores_markers(mocker):
    """
  If both 'card id' and 'markers' args are specified, 'markers' are ignored.
  """

    card_obj1 = knards.Card(markers='python specific test')
    card_obj2 = knards.Card(markers='python')
    card_obj3 = knards.Card(markers='python specific test')

    runner = CliRunner()
    with runner.isolated_filesystem():
        # create the DB
        runner.invoke(knards.main, ['bootstrap-db'])
        db_path = os.getcwd() + '/' + config.DB
        mocker.patch('knards.config.get_DB_name', return_value=db_path)

        # create cards
        api.create_card(card_obj1)
        api.create_card(card_obj2)
        api.create_card(card_obj3)

        # check that cards were successfully stored
        assert len(api.get_card_set()) == 3

        # invoke the subcommand
        result = runner.invoke(knards.main,
                               ['delete', '--id', 1, '--m', 'python'])
        assert result.exit_code == 0
        assert len(api.get_card_set()) == 2
def test_if_card_has_date_updated_none_its_swapped_with_never_in_output(
  mocker
):
  """
  If a card in the DB has its .date_updated equal None, it's displayed as
  "Never" in the subcommand's output.
  .date_updated equals None by default for every new card.
  """
  card_obj1 = knards.Card()
  card_obj2 = knards.Card(date_updated='2019-08-30')
  card_obj3 = knards.Card()

  runner = CliRunner()
  with runner.isolated_filesystem():
    # create the DB
    runner.invoke(knards.main, ['bootstrap-db'])
    # store the card
    db_path = os.getcwd() + '/' + config.DB
    api.create_card(card_obj1, db_path)
    api.create_card(card_obj2, db_path)
    api.create_card(card_obj3, db_path)

    mocker.patch('knards.util.open_in_editor')

    runner.invoke(knards.main, ['list'])
    assert util.open_in_editor.call_args_list[0][0][0].count('Never') == 2
Beispiel #7
0
def test_performance_on_11000_cards(init_db):
    """
  In this test we simulate a creation of 11000 cards (and storing them in the
  DB) and the following fetching for them in the DB, with respect to different
  constraints specified.
  """
    for i in range(10000):
        api.create_card(knards.Card(markers='first second third'), init_db)

    for i in range(1000):
        api.create_card(knards.Card(markers='first second fourth'), init_db)

    set1 = api.get_card_set(include_markers=['second'], db_path=init_db)
    set2 = api.get_card_set(include_markers=['second', 'third'],
                            db_path=init_db)
    set3 = api.get_card_set(include_markers=['second'],
                            exclude_markers=['third'],
                            db_path=init_db)

    assert len(set1) == 11000
    assert len(set2) == 10000
    assert len(set3) == 1000
Beispiel #8
0
def test_buffer_contains_metadata_question_and_answer(mocker):
    """
  The buffer that is opened in the editor contains all card's metadata, the
  question text, and the answer text.
  """
    card_obj1 = knards.Card()
    card_obj2 = knards.Card(markers='python specific',
                            series='Some Series',
                            pos_in_series=3,
                            question='Some Text For The Question',
                            answer='A sample answer')

    runner = CliRunner()
    with runner.isolated_filesystem():
        # create the DB
        runner.invoke(knards.main, ['bootstrap-db'])

        # store the card
        db_path = os.getcwd() + '/' + config.DB
        mocker.patch('knards.config.get_DB_name', return_value=db_path)

        api.create_card(card_obj1)
        api.create_card(card_obj2)

        mocker.patch('knards.util.open_in_editor', side_effect=Exception)

        # invoke the subcommand
        result = runner.invoke(knards.main, ['edit', '--id', 2])
        assert result.exit_code == 1
        assert card_obj2.markers in util.open_in_editor.call_args_list[0][0][0]
        assert card_obj2.series in util.open_in_editor.call_args_list[0][0][0]
        assert str(card_obj2.pos_in_series) in \
          util.open_in_editor.call_args_list[0][0][0]
        assert card_obj2.question in util.open_in_editor.call_args_list[0][0][
            0]
        assert card_obj2.answer in util.open_in_editor.call_args_list[0][0][0]
        assert \
          util.open_in_editor.call_args_list[0][0][0].count(msg.DIVIDER_LINE) == 2
def test_fail_if_input_arg_is_not_a_proper_card_object(init_db):
    """
  update_card() takes in only one argument and it must be of type knards.Card
  update_card() always returns a boolean value.
  """
    card_obj = knards.Card()
    card_id = api.create_card(card_obj, init_db)

    result = api.update_card(111, init_db)
    assert result == False

    result = api.update_card('not a card', init_db)
    assert result == False

    result = api.update_card(card_obj, init_db)
    assert result == True
def test_if_no_args_passed_in_method_returns_the_last_stored_card(init_db):
    """
  If no arguments are passed to the get_last_card() method, the method returns
  the card with the largest id from the set of cards with the most recent
  .date_created
  """
    card_obj1 = knards.Card(date_created=(datetime.today() -
                                          timedelta(1)).strftime('%Y-%m-%d'), )
    card_obj2 = knards.Card()
    card_obj3 = knards.Card()
    card_obj4 = knards.Card(date_created=(datetime.today() -
                                          timedelta(1)).strftime('%Y-%m-%d'), )
    api.create_card(card_obj1, init_db)
    api.create_card(card_obj2, init_db)
    api.create_card(card_obj3, init_db)
    api.create_card(card_obj4, init_db)

    result = api.get_last_card(db_path=init_db)
    assert result.id == 3
Beispiel #11
0
def test_all_cards_containing_all_markers_are_deleted_if_markers_is_specified(
        mocker):
    """
  If 'markers' arg is specified, delete ALL the cards that have ALL the markers
  that are specified.
  """

    card_obj1 = knards.Card(markers='python specific test')
    card_obj2 = knards.Card(markers='python')
    card_obj3 = knards.Card(markers='python specific test')
    card_obj4 = knards.Card(markers='python specifico test')

    runner = CliRunner()
    with runner.isolated_filesystem():
        # create the DB
        runner.invoke(knards.main, ['bootstrap-db'])
        db_path = os.getcwd() + '/' + config.DB
        mocker.patch('knards.config.get_DB_name', return_value=db_path)

        # create cards
        api.create_card(card_obj1)
        api.create_card(card_obj2)
        api.create_card(card_obj3)
        api.create_card(card_obj4)

        # check that cards were successfully stored
        assert len(api.get_card_set()) == 4

        # invoke the subcommand
        result = runner.invoke(knards.main,
                               ['delete', '--m', 'python,specific test'])
        assert result.exit_code == 0

        # two cards should be deleted, two that's left have ids 2 and 4
        assert len(api.get_card_set()) == 2
        assert api.get_card_set()[0].id == 2
        assert api.get_card_set()[1].id == 4

        # in development we don't allow to delete all cards at once using markers
        result = runner.invoke(knards.main, ['delete', '--m', 'python'])
        assert result.exit_code == 1
        assert len(api.get_card_set()) == 2
def test_card_id_arg_must_be_a_number(mocker, init_db):
  """
  One of the arguments delete_card() takes in is card_id, which must be a
  proper integer number.
  """
  card_obj = knards.Card()
  card_id = api.create_card(card_obj, init_db)
  assert card_id == 1

  mocker.patch(
    'knards.api.get_card_by_id',
    return_value=api.get_card_by_id(card_id, init_db)
  )

  result = api.delete_card(card_id='1', db_path=init_db)
  assert result is False

  result = api.delete_card(card_id=1, db_path=init_db)
  assert result is True
def test_if_card_id_and_markers_are_passed_in_markers_are_ignored(
  mocker,
  init_db
):
  """
  If both card_id and markers are passed to the delete_card() method, markers
  are ignored and only the card with the card_id id is removed from the DB.
  """
  card_obj1 = knards.Card(markers='python specific')
  card_obj2 = knards.Card(markers='python nonspecific')
  card_obj3 = knards.Card(markers='javascript specific')
  api.create_card(card_obj1, init_db)
  api.create_card(card_obj2, init_db)
  api.create_card(card_obj3, init_db)

  assert len(api.get_card_set(db_path=init_db)) == 3

  mocker.patch(
    'knards.api.get_card_by_id',
    return_value=api.get_card_by_id(1, db_path=init_db)
  )
  mocker.patch(
    'knards.api.get_card_set',
    return_value=api.get_card_set(db_path=init_db)
  )
  assert api.delete_card(
    card_id=4,
    markers=['specific'],
    db_path=init_db
  ) is True
  mocker.stopall()

  assert len(api.get_card_set(db_path=init_db)) == 3

  mocker.patch(
    'knards.api.get_card_by_id',
    return_value=api.get_card_by_id(1, db_path=init_db)
  )
  mocker.patch(
    'knards.api.get_card_set',
    return_value=api.get_card_set(db_path=init_db)
  )
  assert api.delete_card(
    card_id=1,
    markers=['specific'],
    db_path=init_db
  ) is True
  mocker.stopall()

  assert len(api.get_card_set(db_path=init_db)) == 2
def test_card_obj_sent_to_update_card_gets_properly_updated(init_db):
    """
  update_card() should take in an object of type knards.Card and update it in
  the DB.
  """
    initial_card_obj = knards.Card()
    initial_card_id = api.create_card(initial_card_obj, init_db)

    stored_card_obj = api.get_card_by_id(initial_card_id, init_db)
    stored_card_obj = stored_card_obj._replace(question='new contents',
                                               score=12)
    api.update_card(stored_card_obj, init_db)

    updated_card_obj = api.get_card_by_id(initial_card_id, init_db)
    assert updated_card_obj.id == initial_card_id
    assert updated_card_obj.question == 'new contents'
    assert updated_card_obj.answer == initial_card_obj.answer
    assert updated_card_obj.markers == initial_card_obj.markers
    assert updated_card_obj.date_created == initial_card_obj.date_created
    assert updated_card_obj.date_updated == datetime.today().strftime(
        '%Y-%m-%d')
    assert initial_card_obj.date_updated is None
def test_if_card_id_is_passed_in_method_deletes_the_card_with_that_id(
  mocker,
  init_db
):
  """
  If card_id argument is passed to the delete_card() method, the card with
  that id is removed from the DB.
  """
  card_obj = knards.Card()
  card_id = api.create_card(card_obj, init_db)

  result = api.get_card_by_id(card_id, init_db)
  assert result.id == card_id

  mocker.patch(
    'knards.api.get_card_by_id',
    return_value=api.get_card_by_id(card_id, init_db)
  )
  api.delete_card(card_id=card_id, db_path=init_db)
  mocker.stopall()

  result = api.get_card_by_id(card_id, init_db)
  assert result is None
Beispiel #16
0
def test_if_today_is_true_return_only_cards_that_were_reviewed_today(init_db):
  """
  If today=True is passed to get_card_set(), return cards that have
  .date_updated equal to today's date.
  """
  card_obj1 = knards.Card()
  card_obj2 = knards.Card(
    date_updated=datetime.today().strftime('%Y-%m-%d'),
    score=1
  )
  card_obj3 = knards.Card(
    date_created=(datetime.today() - timedelta(10)).strftime('%Y-%m-%d'),
    score=2
  )

  api.create_card(card_obj1, init_db)
  api.create_card(card_obj2, init_db)
  api.create_card(card_obj3, init_db)

  assert len(api.get_card_set(today=True, db_path=init_db)) == 1
  assert len(api.get_card_set(today=False, db_path=init_db)) == 3
Beispiel #17
0
def test_if_revisable_only_is_true_return_only_cards_ready_for_revision(init_db):
  """
  If revisable_only=True is passed to get_card_set(), return cards that either
  don't have .date_updated set (None) or have their .score less than or equal
  to the difference between today and its .date_updated in days.
  """
  card_obj1 = knards.Card()
  card_obj2 = knards.Card(
    date_updated=(datetime.today() - timedelta(1)).strftime('%Y-%m-%d'),
    score=1
  )
  card_obj3 = knards.Card(
    date_updated=(datetime.today() - timedelta(1)).strftime('%Y-%m-%d'),
    score=2
  )

  api.create_card(card_obj1, init_db)
  api.create_card(card_obj2, init_db)
  api.create_card(card_obj3, init_db)

  assert len(api.get_card_set(revisable_only=False, db_path=init_db)) == 3
  assert len(api.get_card_set(revisable_only=True, db_path=init_db)) == 2
def test_if_markers_passed_in_method_returns_true_always(mocker, init_db):
  """
  If no cards contain the specified set of markers, no cards are removed from
  the DB and True is returned.
  """
  card_obj1 = knards.Card(markers='python specific')
  card_obj2 = knards.Card(markers='python nonspecific')
  card_obj3 = knards.Card(markers='javascript specific')
  api.create_card(card_obj1, init_db)
  api.create_card(card_obj2, init_db)
  api.create_card(card_obj3, init_db)

  assert len(api.get_card_set(db_path=init_db)) == 3

  mocker.patch(
    'knards.api.get_card_set',
    return_value=api.get_card_set(db_path=init_db)
  )
  assert api.delete_card(markers=['specific', 'test'], db_path=init_db) is True
  mocker.stopall()

  assert len(api.get_card_set(db_path=init_db)) == 3
def test_method_returns_a_proper_card_obj_upon_success(mocker, init_db):
    """
  get_last_card() returns an object of type knards.Card that is a copy of the
  last stored card object.
  If markers argument is passed to the method, it returns an object of type
  knards.Card that is a copy of the last stored card that has ALL of the
  specified markers.
  """
    card_obj1 = knards.Card(markers='python specific test')
    card_obj2 = knards.Card(markers='javascript specific')
    card_obj3 = knards.Card(markers='javascript specific test',
                            date_created=(datetime.today() -
                                          timedelta(1)).strftime('%Y-%m-%d'))
    api.create_card(card_obj1, init_db)
    api.create_card(card_obj2, init_db)
    api.create_card(card_obj3, init_db)

    mocker.patch('knards.api.get_card_set',
                 return_value=api.get_card_set(db_path=init_db))
    result = api.get_last_card(db_path=init_db)
    assert result.id == 2

    result = api.get_last_card(markers=['specific', 'test'], db_path=init_db)
    assert result.id == 1
Beispiel #20
0
def test_if_markers_passed_return_cards_with_respect_to_constraints(init_db):
  """
  If get_card_set() is passed include_markers=[...], return only cards that
  have ALL of the specified markers.
  If get_card_set() is passed exclude_markers=[...], return only cards that
  have NONE of the specified markers.
  """
  card_obj1 = knards.Card(markers='python specific')
  card_obj2 = knards.Card(markers='javascript specific')
  card_obj3 = knards.Card(markers='python nonspecific')
  card_obj4 = knards.Card(markers='javascript test')
  card_obj5 = knards.Card(markers='javascript test special')
  card_obj6 = knards.Card(markers='javascript python')
  api.create_card(card_obj1, init_db)
  api.create_card(card_obj2, init_db)
  api.create_card(card_obj3, init_db)
  api.create_card(card_obj4, init_db)
  api.create_card(card_obj5, init_db)
  api.create_card(card_obj6, init_db)

  assert len(api.get_card_set(
    include_markers=['test'],
    db_path=init_db
  )) == 2
  assert len(api.get_card_set(
    include_markers=['specific'],
    db_path=init_db
  )) == 2
  assert len(api.get_card_set(
    include_markers=['spec'],
    db_path=init_db
  )) == 0
  assert len(api.get_card_set(
    include_markers=['javascript'],
    db_path=init_db
  )) == 4
  assert len(api.get_card_set(
    include_markers=['special', 'javascript'],
    db_path=init_db
  )) == 1
  assert len(api.get_card_set(
    exclude_markers=['javascript'],
    db_path=init_db
  )) == 2
  assert len(api.get_card_set(
    exclude_markers=['python', 'test'],
    db_path=init_db
  )) == 1
  assert len(api.get_card_set(
    exclude_markers=['specific'],
    db_path=init_db
  )) == 4
  assert len(api.get_card_set(
    exclude_markers=['specific', 'test'],
    db_path=init_db
  )) == 2
Beispiel #21
0
def merge(db_file):
    """
    TODO
    """

    # check if merge file exists and is a proper DB file
    try:
        with util.db_connect(db_file) as connection:
            cursor = connection.cursor()
            cursor.execute("""
                SELECT * FROM cards
            """)
            card_set = cursor.fetchall()

        card_set_as_objects = []
        for card in card_set:
            card_set_as_objects.append(Card(*card))

        full_card_set = api.get_card_set()
        dates = []
        for card in full_card_set:
            dates.append(card.date_created)

    except exceptions.DBFileNotFound as e:
        print(e.args[0])
        sys.exit(1)
    except sqlite3.DatabaseError:
        print('{} is not a proper DB file to merge.'.format(db_file))
        sys.exit(1)

    # backup both DB files
    try:
        copyfile(
            config.get_DB_name(),
            config.get_backup_path() +
            'main_{}'.format(datetime.now().strftime('%Y_%m_%d_%H_%M_%S_%f')))
    except IOError as e:
        print("Unable to copy file. %s" % e)
        sys.exit(1)
    except:
        print("Unexpected error:", sys.exc_info())
        sys.exit(1)

    try:
        copyfile(
            db_file,
            config.get_backup_path() +
            'merge_{}'.format(datetime.now().strftime('%Y_%m_%d_%H_%M_%S_%f')))
    except IOError as e:
        print("Unable to copy file. %s" % e)
        sys.exit(1)
    except:
        print("Unexpected error:", sys.exc_info())
        sys.exit(1)

    # merge
    merged = 0
    skipped = 0
    for card in card_set_as_objects:
        if card.date_created in dates:
            skipped += 1
            continue

        merged += 1
        api.create_card(card)

    if skipped == 0:
        click.secho(
            'DB file ({}) was successfully merged into the default DB file.'.
            format(db_file),
            fg='green',
            bold=True)

        os.remove(db_file)
    else:
        click.secho(
            '{} cards merged; {} cards skipped; You might be trying to merge a DB \
      file that was already merged.\nMerged DB file wasn\'t removed in case \
      something went wrong, please check manually and then remove the file.'.
            format(merged, skipped),
            fg='red',
            bold=True)
Beispiel #22
0
def new(qf, copy_last, copy_from_id, markers):
    """
    Prompt to create a new card.

    $ kn new
    Opens a "question-first" buffer in editor, processes what's in the buffer
    after "save & exit", sends into the second buffer (for answer), processes
    what's returned by that, checks if the format is OK, splits up metadata and
    card's text, generates an object of type knards.Card and feeds it to the
    create_card()

    $ kn new --af
    Opens a "answer-first" buffer in editor, processes what's in the buffer
    after "save & exit", sends into the second buffer (for question), processes
    what's returned by that, checks if the format is OK, splits up metadata and
    card's text, generates an object of type knards.Card and feeds it to the
    create_card()
    """

    if markers is not None:
        markers = markers.split(',')
    else:
        markers = []

    if copy_last:
        card_obj = api.get_last_card(markers=markers)
        prompt = 'Markers: [{}]\n'.format(card_obj.markers)
        prompt += 'Series: [{}]\n'.format(card_obj.series)
    elif copy_from_id:
        card_obj = api.get_card_by_id(copy_from_id)
        prompt = 'Markers: [{}]\n'.format(card_obj.markers)
        prompt += 'Series: [{}]\n'.format(card_obj.series)
    else:
        card_obj = Card()
        prompt = 'Markers: []\n'
        prompt += 'Series: []\n'

    card_obj = card_obj._replace(date_created=datetime.now())
    card_obj = card_obj._replace(date_updated=None)
    if card_obj.series:
        card_obj = card_obj._replace(pos_in_series=card_obj.pos_in_series + 1)
    else:
        card_obj = card_obj._replace(pos_in_series=card_obj.pos_in_series)
    card_obj = card_obj._replace(score=0)

    prompt += 'No. in series: {}\n'.format(card_obj.pos_in_series)
    prompt += msg.DIVIDER_LINE + '\n'

    if qf:
        prompt += card_obj.question + '\n'

        valid = False
        retry_count = 1
        submit_question = prompt
        while not valid:
            submit_question = util.open_in_editor(submit_question)

            try:
                submit_question, valid = util.check_buffer(
                    'new', submit_question)
            except exceptions.BadBufferFormat as e:
                print(e.args[0])

            if not valid:
                if not util.retry_buffer(retry_count):
                    sys.exit(7)

        valid = False
        retry_count = 1
        submit_answer = submit_question
        while not valid:
            submit_answer = util.open_in_editor(submit_answer)

            try:
                submit_answer, valid = util.check_buffer('new', submit_answer)
            except exceptions.BadBufferFormat as e:
                print(e.args[0])

            if not valid:
                if not util.retry_buffer(retry_count):
                    sys.exit(7)

        question_text = ''
        for index, line in enumerate(submit_question.split('\n')):
            if index > 3:
                question_text += line + '\n'
        else:
            card_obj = card_obj._replace(question=question_text)

        answer_text = ''
        for index, line in enumerate(submit_answer.split('\n')):
            if index == 0:
                card_obj = card_obj._replace(
                    markers=line.split('[')[1].split(']')[0])
            if index == 1:
                card_obj = card_obj._replace(
                    series=line.split('[')[1].split(']')[0])
            if index == 2:
                card_obj = card_obj._replace(
                    pos_in_series=int(line.split(':')[1][1:]))
            if index > 3:
                answer_text += line + '\n'
        else:
            card_obj = card_obj._replace(answer=answer_text)

        card_id = api.create_card(card_obj)
        if card_id:
            click.secho(msg.NEW_CARD_SUCCESS.format(card_id),
                        fg='green',
                        bold=True)
        else:
            click.secho(msg.NEW_CARD_FAILURE, fg='red', bold=True)

    else:
        prompt += card_obj.answer + '\n'

        valid = False
        retry_count = 1
        submit_answer = prompt
        while not valid:
            submit_answer = util.open_in_editor(submit_answer)

            try:
                submit_answer, valid = util.check_buffer('new', submit_answer)
            except exceptions.BadBufferFormat as e:
                print(e.args[0])

            if not valid:
                if not util.retry_buffer(retry_count):
                    sys.exit(7)

        valid = False
        retry_count = 1
        submit_question = submit_answer
        while not valid:
            submit_question = util.open_in_editor(submit_question)

            try:
                submit_question, valid = util.check_buffer(
                    'new', submit_question)
            except exceptions.BadBufferFormat as e:
                print(e.args[0])

            if not valid:
                if not util.retry_buffer(retry_count):
                    sys.exit(7)

        question_text = ''
        for index, line in enumerate(submit_question.split('\n')):
            if index == 0:
                card_obj = card_obj._replace(
                    markers=line.split('[')[1].split(']')[0])
            if index == 1:
                card_obj = card_obj._replace(
                    series=line.split('[')[1].split(']')[0])
            if index == 2:
                card_obj = card_obj._replace(
                    pos_in_series=int(line.split(':')[1][1:]))
            if index > 3:
                question_text += line + '\n'
        else:
            card_obj = card_obj._replace(question=question_text)

        answer_text = ''
        for index, line in enumerate(submit_answer.split('\n')):
            if index > 3:
                answer_text += line + '\n'
        else:
            card_obj = card_obj._replace(answer=answer_text)

        card_id = api.create_card(card_obj)
        if card_id:
            click.secho(msg.NEW_CARD_SUCCESS.format(card_id),
                        fg='green',
                        bold=True)
        else:
            click.secho(msg.NEW_CARD_FAILURE, fg='red', bold=True)
def test_if_markers_passed_in_all_cards_with_those_markers_are_removed(
  mocker,
  init_db
):
  """
  If markers list is passed to the delete_card() method, all cards that contain
  ALL of the specified markers are being removed from the DB.
  """
  card_obj1 = knards.Card(markers='python specific')
  card_obj2 = knards.Card(markers='python nonspecific')
  card_obj3 = knards.Card(markers='javascript specific test')
  card_obj4 = knards.Card(markers='python special')
  card_obj5 = knards.Card(markers='python specific test')
  card_obj6 = knards.Card(markers='specifically test')
  api.create_card(card_obj1, init_db)
  api.create_card(card_obj2, init_db)
  api.create_card(card_obj3, init_db)
  api.create_card(card_obj4, init_db)
  api.create_card(card_obj5, init_db)
  api.create_card(card_obj6, init_db)

  assert len(api.get_card_set(db_path=init_db)) == 6

  mocker.patch(
    'knards.api.get_card_set',
    return_value=api.get_card_set(db_path=init_db)
  )
  assert api.delete_card(markers=['specific', 'test'], db_path=init_db) is True
  mocker.stopall()

  assert len(api.get_card_set(db_path=init_db)) == 4