|
26 | 26 | from mock import patch |
27 | 27 |
|
28 | 28 | from neo4j.v1.constants import TRUST_ON_FIRST_USE |
29 | | -from neo4j.v1.exceptions import CypherError |
| 29 | +from neo4j.v1.exceptions import CypherError, ResultError |
30 | 30 | from neo4j.v1.session import GraphDatabase, basic_auth, Record, SSL_AVAILABLE |
31 | 31 | from neo4j.v1.types import Node, Relationship, Path |
32 | 32 |
|
@@ -575,3 +575,74 @@ def test_can_consume_result_after_session_with_error(self): |
575 | 575 | tx.commit() |
576 | 576 | session.close() |
577 | 577 | assert [record[0] for record in result] == [1, 2, 3] |
| 578 | + |
| 579 | + def test_single_with_exactly_one_record(self): |
| 580 | + session = self.driver.session() |
| 581 | + result = session.run("UNWIND range(1, 1) AS n RETURN n") |
| 582 | + record = result.single() |
| 583 | + assert list(record.values()) == [1] |
| 584 | + |
| 585 | + def test_single_with_no_records(self): |
| 586 | + session = self.driver.session() |
| 587 | + result = session.run("CREATE ()") |
| 588 | + with self.assertRaises(ResultError): |
| 589 | + result.single() |
| 590 | + |
| 591 | + def test_single_with_multiple_records(self): |
| 592 | + session = self.driver.session() |
| 593 | + result = session.run("UNWIND range(1, 3) AS n RETURN n") |
| 594 | + with self.assertRaises(ResultError): |
| 595 | + result.single() |
| 596 | + |
| 597 | + def test_single_consumes_entire_result_if_one_record(self): |
| 598 | + session = self.driver.session() |
| 599 | + result = session.run("UNWIND range(1, 1) AS n RETURN n") |
| 600 | + _ = result.single() |
| 601 | + assert result._consumed |
| 602 | + |
| 603 | + def test_single_consumes_entire_result_if_multiple_records(self): |
| 604 | + session = self.driver.session() |
| 605 | + result = session.run("UNWIND range(1, 3) AS n RETURN n") |
| 606 | + with self.assertRaises(ResultError): |
| 607 | + _ = result.single() |
| 608 | + assert result._consumed |
| 609 | + |
| 610 | + def test_peek_can_look_one_ahead(self): |
| 611 | + session = self.driver.session() |
| 612 | + result = session.run("UNWIND range(1, 3) AS n RETURN n") |
| 613 | + record = result.peek() |
| 614 | + assert list(record.values()) == [1] |
| 615 | + |
| 616 | + def test_peek_fails_if_nothing_remains(self): |
| 617 | + session = self.driver.session() |
| 618 | + result = session.run("CREATE ()") |
| 619 | + with self.assertRaises(ResultError): |
| 620 | + result.peek() |
| 621 | + |
| 622 | + def test_peek_does_not_advance_cursor(self): |
| 623 | + session = self.driver.session() |
| 624 | + result = session.run("UNWIND range(1, 3) AS n RETURN n") |
| 625 | + result.peek() |
| 626 | + assert [record[0] for record in result] == [1, 2, 3] |
| 627 | + |
| 628 | + def test_peek_at_different_stages(self): |
| 629 | + session = self.driver.session() |
| 630 | + result = session.run("UNWIND range(0, 9) AS n RETURN n") |
| 631 | + # Peek ahead to the first record |
| 632 | + expected_next = 0 |
| 633 | + upcoming = result.peek() |
| 634 | + assert upcoming[0] == expected_next |
| 635 | + # Then look through all the other records |
| 636 | + for expected, record in enumerate(result): |
| 637 | + # Check this record is as expected |
| 638 | + assert record[0] == expected |
| 639 | + # Check the upcoming record is as expected... |
| 640 | + if expected < 9: |
| 641 | + # ...when one should follow |
| 642 | + expected_next = expected + 1 |
| 643 | + upcoming = result.peek() |
| 644 | + assert upcoming[0] == expected_next |
| 645 | + else: |
| 646 | + # ...when none should follow |
| 647 | + with self.assertRaises(ResultError): |
| 648 | + result.peek() |
0 commit comments