From 2be53c9c539cc7fea721733c8735609cb8a51a00 Mon Sep 17 00:00:00 2001 From: David Watkins Date: Tue, 8 Aug 2023 18:08:01 +0100 Subject: [PATCH 1/2] Added playwright test for survey creation and issuance - survey template creation - single direct issuance - issuance via run #6071 --- waltz-ng/client/survey/survey-run-create.html | 3 +- .../test_common/helpers/PersonHelper.java | 3 +- .../playwright/ScreenshotHelper.java | 64 +++- .../waltz/test_common/playwright/Section.java | 1 + .../RuleCreationTest.java | 16 +- .../SurveyIssuanceIntegrationTest.java | 290 ++++++++++++++++++ 6 files changed, 360 insertions(+), 17 deletions(-) create mode 100644 waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/surveys/SurveyIssuanceIntegrationTest.java diff --git a/waltz-ng/client/survey/survey-run-create.html b/waltz-ng/client/survey/survey-run-create.html index 5b65a6d9b4..38757a535a 100644 --- a/waltz-ng/client/survey/survey-run-create.html +++ b/waltz-ng/client/survey/survey-run-create.html @@ -46,7 +46,8 @@ -
+

Issue Survey


diff --git a/waltz-test-common/src/main/java/org/finos/waltz/test_common/helpers/PersonHelper.java b/waltz-test-common/src/main/java/org/finos/waltz/test_common/helpers/PersonHelper.java index 5928e16f16..5a056c1ab0 100644 --- a/waltz-test-common/src/main/java/org/finos/waltz/test_common/helpers/PersonHelper.java +++ b/waltz-test-common/src/main/java/org/finos/waltz/test_common/helpers/PersonHelper.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; import static org.finos.waltz.schema.tables.Person.PERSON; @@ -29,7 +30,7 @@ public Long createPerson(String name) { p.setEmail(name); p.setKind(PersonKind.EMPLOYEE.name()); p.setDisplayName(name); - p.setEmployeeId(Long.toString(ctr.incrementAndGet())); + p.setEmployeeId(UUID.randomUUID().toString()); p.insert(); return p.getId(); diff --git a/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/ScreenshotHelper.java b/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/ScreenshotHelper.java index 5c07300673..6f2e1666bc 100644 --- a/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/ScreenshotHelper.java +++ b/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/ScreenshotHelper.java @@ -2,13 +2,20 @@ import com.microsoft.playwright.Locator; import com.microsoft.playwright.Page; +import org.finos.waltz.common.StringUtilities; +import java.nio.file.Path; import java.nio.file.Paths; +import java.util.concurrent.atomic.AtomicInteger; +import static java.lang.String.format; import static org.finos.waltz.common.StringUtilities.mkPath; public class ScreenshotHelper { + private AtomicInteger counter = new AtomicInteger(0); + private boolean paused = false; + private final Page page; private final String basePath; @@ -19,20 +26,63 @@ public ScreenshotHelper(Page page, String basePath) { public Locator takeElemSnapshot(Locator locator, String name) { - locator.screenshot(new Locator - .ScreenshotOptions() - .setPath(Paths.get(mkPath(basePath, name)))); + if (! paused) { + Locator.ScreenshotOptions options = new Locator.ScreenshotOptions() + .setPath(mkPath(name)); + + locator.screenshot(options); + } return locator; } - public Locator takePageSnapshot(Locator locator, String name) { + public Page takePageSnapshot(Page page, String name) { + if (! paused) { + Page.ScreenshotOptions options = new Page.ScreenshotOptions() + .setPath(mkPath(name)); + + page.screenshot(options); + } + return page; + } + + public Locator takePageSnapshot(Locator locator, String name) { locator.waitFor(); - page.screenshot(new Page - .ScreenshotOptions() - .setPath(Paths.get(mkPath(basePath, name)))); + locator.scrollIntoViewIfNeeded(); + + if (! paused) { + Page.ScreenshotOptions options = new Page + .ScreenshotOptions() + .setPath(mkPath(name)); + + page.screenshot(options); + } + return locator; } + + + public ScreenshotHelper pause() { + this.paused = true; + return this; + } + + + public ScreenshotHelper resume() { + this.paused = false; + return this; + } + + + // -- HELPER --- + + private Path mkPath(String name) { + return Paths.get(StringUtilities.mkPath( + basePath, + format("%d_%s", counter.incrementAndGet(), name))); + } + + } diff --git a/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/Section.java b/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/Section.java index 4d05755582..a8a747ef68 100644 --- a/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/Section.java +++ b/waltz-test-common/src/main/java/org/finos/waltz/test_common/playwright/Section.java @@ -4,6 +4,7 @@ * List of the waltz ui sections and their id's. */ public enum Section { + APP_SURVEYS(17), ASSESSMENTS(200), BOOKMARKS(5); diff --git a/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/flow_classification_rule/RuleCreationTest.java b/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/flow_classification_rule/RuleCreationTest.java index 7ab6535468..a270ce5284 100644 --- a/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/flow_classification_rule/RuleCreationTest.java +++ b/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/flow_classification_rule/RuleCreationTest.java @@ -53,7 +53,7 @@ public void add() throws InterruptedException { screenshotHelper.takePageSnapshot( listLocator, - "1_show_list.png"); + "show_list.png"); listLocator .getByTestId("create-rule") @@ -61,7 +61,7 @@ public void add() throws InterruptedException { Locator formLocator = screenshotHelper.takePageSnapshot( page.getByTestId("flow-classification-rule-editor"), - "2_create_rule.png"); + "create_rule.png"); formLocator .locator("#source") @@ -73,7 +73,7 @@ public void add() throws InterruptedException { .locator("#source") .locator(".autocomplete-list-item") .locator(format("text=%s", toName(appRef))), - "3_select_app.png"); + "select_app.png"); appLocator.click(); @@ -82,7 +82,7 @@ public void add() throws InterruptedException { formLocator .locator("#datatype") .locator("text=Book Data"), - "4_select_datatype.png") + "select_datatype.png") .click(); formLocator @@ -96,7 +96,7 @@ public void add() throws InterruptedException { .locator("#scope") .locator(".autocomplete-list-item") .locator("text=CEO Office"), - "5_select_scope.png") + "select_scope.png") .click(); Locator ratingLocator = formLocator @@ -107,7 +107,7 @@ public void add() throws InterruptedException { screenshotHelper.takePageSnapshot( ratingLocator, - "6_select_rating.png"); + "select_rating.png"); formLocator .locator("button[type=submit]") @@ -118,7 +118,7 @@ public void add() throws InterruptedException { screenshotHelper.takePageSnapshot( page.locator(".waltz-flow-classification-rules-table"), - "7_result.png"); + "result.png"); Thread.sleep(1000); @@ -130,7 +130,7 @@ public void add() throws InterruptedException { screenshotHelper.takePageSnapshot( page.getByTestId("source"), - "8_view.png"); + "view.png"); assertThat(page.getByTestId("source")).containsText(toName(appRef)); assertThat(page.getByTestId("data-type")).containsText("Book Data"); diff --git a/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/surveys/SurveyIssuanceIntegrationTest.java b/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/surveys/SurveyIssuanceIntegrationTest.java new file mode 100644 index 0000000000..bfbba0fce3 --- /dev/null +++ b/waltz-test-common/src/test/java/org/finos/waltz/test_common/playwright/surveys/SurveyIssuanceIntegrationTest.java @@ -0,0 +1,290 @@ +package org.finos.waltz.test_common.playwright.surveys; + + +import com.microsoft.playwright.Locator; +import org.finos.waltz.common.exception.InsufficientPrivelegeException; +import org.finos.waltz.model.EntityReference; +import org.finos.waltz.model.survey.ImmutableSurveyQuestion; +import org.finos.waltz.model.survey.SurveyQuestion; +import org.finos.waltz.model.survey.SurveyQuestionFieldType; +import org.finos.waltz.test_common.helpers.AppGroupHelper; +import org.finos.waltz.test_common.helpers.AppHelper; +import org.finos.waltz.test_common.helpers.InvolvementHelper; +import org.finos.waltz.test_common.helpers.PersonHelper; +import org.finos.waltz.test_common.playwright.BasePlaywrightIntegrationTest; +import org.finos.waltz.test_common.playwright.ScreenshotHelper; +import org.finos.waltz.test_common.playwright.Section; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.io.IOException; +import java.time.LocalDate; + +import static com.microsoft.playwright.assertions.PlaywrightAssertions.assertThat; +import static org.finos.waltz.common.SetUtilities.asSet; +import static org.finos.waltz.common.StringUtilities.mkPath; +import static org.finos.waltz.test_common.helpers.NameHelper.mkName; +import static org.finos.waltz.test_common.playwright.PlaywrightUtilities.*; + + +/** + * This demonstrates a basic test which uses the integration test helpers + * to prep test data. + */ +public class SurveyIssuanceIntegrationTest extends BasePlaywrightIntegrationTest { + + @Autowired + private AppHelper appHelper; + + + @Autowired + private AppGroupHelper appGroupHelper; + + @Autowired + private InvolvementHelper involvementHelper; + + @Autowired + private PersonHelper personHelper; + + + @BeforeEach + public void setup() throws IOException { + login(page, BASE); + } + + + @Test + public void createTemplate() { + String name = mkName("surveys-create-template"); + ScreenshotHelper screenshotHelper = new ScreenshotHelper( + page, + "screenshots/survey/create-template"); + createSurveyTemplate(screenshotHelper, name); + activateSurveyTemplate(screenshotHelper, name); + } + + + @Test + public void singleIssuance() { + String name = mkName("surveys-single-issuance"); + ScreenshotHelper screenshotHelper = new ScreenshotHelper( + page, + "screenshots/survey/single-issuance"); + + screenshotHelper.pause(); + + EntityReference appRef = createAppAndInvolvements(name); + + createSurveyTemplate(screenshotHelper, name); + activateSurveyTemplate(screenshotHelper, name); + + screenshotHelper.resume(); + + // navigate to app surveys and verify no + page.navigate(mkPath(BASE, mkEmbeddedFrag(Section.APP_SURVEYS, appRef))); + screenshotHelper.takePageSnapshot(page, "surveys_for_app.png"); + assertThat(page.locator("waltz-no-data")).isVisible(); + + page.locator(".waltz-section-actions .btn").getByText("Issue new survey").click(); + screenshotHelper.takePageSnapshot(page, "issuing_single_survey.png"); + + page.locator("input[type=search]").fill(name); + screenshotHelper.takePageSnapshot(page, "searching_for_template.png"); + + page.locator("td a").getByText(name).click(); + screenshotHelper.takePageSnapshot(page, "template_selected.png"); + + page.fill("input#dueDate", LocalDate.now().plusDays(10).toString()); + page.locator("#recipientInvolvementKinds option[label='" + name + "']").click(); + + screenshotHelper.takePageSnapshot(page, "issuance_params_filled_in.png"); + page.click("form button[type=submit]"); + + assertThat(page.locator("table td").getByText(name).first()).isVisible(); + screenshotHelper.takePageSnapshot(page, "survey_issued.png"); + } + + + @Test + public void runIssuance() throws InsufficientPrivelegeException { + String name = mkName("surveys-run-issuance"); + ScreenshotHelper screenshotHelper = new ScreenshotHelper( + page, + "screenshots/survey/run-issuance"); + + screenshotHelper.pause(); + + EntityReference appRef = createAppAndInvolvements(name); + appGroupHelper.createAppGroupWithAppRefs(name, asSet(appRef)); + + createSurveyTemplate(screenshotHelper, name); + activateSurveyTemplate(screenshotHelper, name); + + screenshotHelper.resume(); + + page.navigate(mkPath(BASE, "/survey/template/list")); + screenshotHelper.takePageSnapshot(page, "survey_list.png"); + page.locator("td a").getByText(name).click(); + screenshotHelper.takePageSnapshot(page, "template-page.png"); + page.locator("waltz-section[name=Runs] .waltz-section-actions").getByText("Create").click(); + screenshotHelper.takePageSnapshot(page, "issuance-params-empty.png"); + + Locator nextBtn = page.locator("button").getByText("Next"); + assertThat(nextBtn).isHidden(); + + page.fill("#email", "test@waltz.com"); + page.fill("input#dueDate", LocalDate.now().plusDays(10).toString()); + page.fill("input#approvalDueDate", LocalDate.now().plusDays(20).toString()); + page.locator("#involvementKinds option[label=" + name + "]").click(); + searchViaUISelect(name); + + screenshotHelper.takePageSnapshot(page.locator("#selectorScope"), "issuance-params-completed.png"); + assertThat(nextBtn).isVisible(); + nextBtn.click(); + + assertThat(page.locator("h4").getByText("Recipients")).isVisible(); + screenshotHelper.takePageSnapshot(page, "verify_issuance_plan.png"); + + assertThat(page.locator("td").getByText(name).first()).isVisible(); + Locator issueBtn = page.locator("waltz-survey-run-create-recipient .btn-success").getByText("Next"); + assertThat(issueBtn).isVisible(); + issueBtn.click(); + + assertThat(page.locator("h4").getByText("Issue Survey")).isVisible(); + assertThat(page.getByTestId("issuance-confirmation")).isVisible(); + screenshotHelper.takePageSnapshot(page, "issued.png"); + + } + + // --- HELPERS --- + + private EntityReference createAppAndInvolvements(String name) { + EntityReference appRef = appHelper.createNewApp( + name, + 10L); + long invKindId = involvementHelper.mkInvolvementKind(name); + long personId = personHelper.createPerson(name); + involvementHelper.createInvolvement(personId, invKindId, appRef); + return appRef; + } + + + private void searchViaUISelect(String name) { + page.locator(".ui-select-match").click(); + page.locator("input.ui-select-search").fill(name); + page.locator(".ui-select-highlight").getByText(name).click(); + } + + + private void activateSurveyTemplate(ScreenshotHelper screenshotHelper, String name) { + // navigate back to overview so we can activate the survey + page.locator(".waltz-breadcrumbs").getByText(name).click(); + screenshotHelper.takePageSnapshot(page, "overview_in_prep_for_marking_as_active.png"); + Locator actionBtns = page.locator(".waltz-page-summary .waltz-section-actions .btn"); + + actionBtns.getByText("Mark as Active").click(); + + assertThat(actionBtns.getByText("Mark as Obsolete")).isVisible(); + assertThat(actionBtns.getByText("Mark as Draft")).isVisible(); + assertThat(actionBtns.getByText("Clone")).isVisible(); + + screenshotHelper.takePageSnapshot(page, "template_is_active.png"); + } + + + private void createSurveyTemplate(ScreenshotHelper screenshotHelper, + String name) { + log("Creating survey template: %s", name); + page.navigate(mkPath(BASE, "/survey/template/list")); + page.locator(".btn").getByText("Create New").click(); + + // check the warning about incompleteness is visible and the submit button is hidden + Locator createTemplateButton = page.locator("button").getByText("Create"); + assertThat(createTemplateButton).isHidden(); + assertThat(page.locator(".alert-warning")).isVisible(); + + // fill in the form + screenshotHelper.takePageSnapshot(page, "create_new.png"); + page.fill("#name", name); + page.fill("#externalId", mkName("TEST_SURVEY")); + page.selectOption("#targetEntityKind", "Application"); + screenshotHelper.takePageSnapshot(page, "create_form_filled_in.png"); + + // check the submit button is visible and the warning has been hidden + assertThat(createTemplateButton).isVisible(); + assertThat(page.locator(".alert-warning")).isHidden(); + + // create the survey and wait for the questions section + createTemplateButton.click(); + Locator questionsSection = page.locator("waltz-section[name=Questions]"); + questionsSection.waitFor(); + screenshotHelper.takeElemSnapshot(questionsSection, "ready_to_add_questions.png"); + + addQuestion( + screenshotHelper, + questionsSection, + ImmutableSurveyQuestion + .builder() + .surveyTemplateId(-1L) // doesn't matter + .questionText("Simple Question: In Scope?") + .externalId("SIMPLE_QUESTION_IN_SCOPE") + .fieldType(SurveyQuestionFieldType.BOOLEAN) + .isMandatory(true) + .helpText("Simple Question Help Text") + .build(), + "q1"); + + addQuestion( + screenshotHelper, + questionsSection, + ImmutableSurveyQuestion + .builder() + .surveyTemplateId(-1L) // doesn't matter + .questionText("Please give more detail") + .externalId("PREDICATE_QUESTION_DETAIL") + .fieldType(SurveyQuestionFieldType.TEXTAREA) + .isMandatory(true) + .inclusionPredicate("isChecked('SIMPLE_QUESTION_IN_SCOPE', false)") + .helpText("Predicate Detail Question Help Text") + .build(), + "q2"); + + } + + + private void addQuestion(ScreenshotHelper screenshotHelper, + Locator questionsSection, + SurveyQuestion question, + String snapshotStem) { + // add a simple question + questionsSection.locator(".waltz-section-actions .btn-primary").getByText("Add New").click(); + screenshotHelper.takeElemSnapshot(questionsSection, snapshotStem + "_adding_question.png"); + Locator questionForm = questionsSection.locator("form[name=surveyQuestionForm]"); + + Locator createQuestionButton = questionsSection.locator("button").getByText("Create"); + assertThat(questionForm.locator(".alert-warning")).isVisible(); + assertThat(createQuestionButton).isHidden(); + + fillInQuestionForm( + questionForm, + question); + + screenshotHelper.takePageSnapshot(questionsSection, snapshotStem + "_question_detail_filled_in.png"); + assertThat(createQuestionButton).isVisible(); + assertThat(questionForm.locator(".alert-warning")).isHidden(); + createQuestionButton.click(); + } + + + private void fillInQuestionForm(Locator questionForm, + SurveyQuestion q) { + questionForm.locator("#qText").fill(q.questionText()); + questionForm.locator("#qExternalId").fill(q.externalId().orElse("")); + questionForm.locator("#qHelpText").fill(q.helpText().orElse("")); + questionForm.locator("#qFieldType").selectOption("string:" + q.fieldType().name()); + questionForm.locator("#qIsMandatory").setChecked(q.isMandatory()); + } + + +} From 726822fb2b9acdd7ee2a981c585f695cf3507d7c Mon Sep 17 00:00:00 2001 From: David Watkins Date: Tue, 8 Aug 2023 23:23:29 +0100 Subject: [PATCH 2/2] Added playwright test for survey creation and issuance - bonus: some extra unit tests #6071 --- .../common/BatchProcessingCollectorTest.java | 31 ++++++++++++++++++ .../waltz/common/Columns_toOffsetTest.java | 15 +++++++++ .../ListUtilities_getOrDefaultTest.java | 22 +++++++++++++ .../common/StreamUtilities_siphonTest.java | 32 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 waltz-common/src/test/java/org/finos/waltz/common/BatchProcessingCollectorTest.java create mode 100644 waltz-common/src/test/java/org/finos/waltz/common/Columns_toOffsetTest.java create mode 100644 waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_getOrDefaultTest.java create mode 100644 waltz-common/src/test/java/org/finos/waltz/common/StreamUtilities_siphonTest.java diff --git a/waltz-common/src/test/java/org/finos/waltz/common/BatchProcessingCollectorTest.java b/waltz-common/src/test/java/org/finos/waltz/common/BatchProcessingCollectorTest.java new file mode 100644 index 0000000000..0996c88228 --- /dev/null +++ b/waltz-common/src/test/java/org/finos/waltz/common/BatchProcessingCollectorTest.java @@ -0,0 +1,31 @@ +package org.finos.waltz.common; + +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class BatchProcessingCollectorTest { + + @Test + public void batchingWorksAndReportsNumberOfItemsProcessed() { + ArrayList data = ListUtilities.newArrayList("A", "B", "C", "D"); + List batched = new ArrayList<>(); + + BatchProcessingCollector batchProcessor = new BatchProcessingCollector<>( + 3, + xs -> { + batched.add(StringUtilities.join(xs, "!")); + }); + + Integer rc = data + .stream() + .collect(batchProcessor); + + assertEquals(4, rc, "Should have processed all input items"); + assertEquals(ListUtilities.asList("A!B!C", "D"), batched); + } +} diff --git a/waltz-common/src/test/java/org/finos/waltz/common/Columns_toOffsetTest.java b/waltz-common/src/test/java/org/finos/waltz/common/Columns_toOffsetTest.java new file mode 100644 index 0000000000..9df97a5b89 --- /dev/null +++ b/waltz-common/src/test/java/org/finos/waltz/common/Columns_toOffsetTest.java @@ -0,0 +1,15 @@ +package org.finos.waltz.common; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Columns_toOffsetTest { + + @Test + public void toOffset() { + assertEquals(Columns.A, Columns.toOffset("A")); + assertEquals(Columns.BA, Columns.toOffset("BA")); + assertEquals(53, Columns.toOffset("BB")); + } +} diff --git a/waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_getOrDefaultTest.java b/waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_getOrDefaultTest.java new file mode 100644 index 0000000000..a44c877994 --- /dev/null +++ b/waltz-common/src/test/java/org/finos/waltz/common/ListUtilities_getOrDefaultTest.java @@ -0,0 +1,22 @@ +package org.finos.waltz.common; + +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.finos.waltz.common.ListUtilities.getOrDefault; +import static org.finos.waltz.common.TestUtilities.assertLength; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ListUtilities_getOrDefaultTest { + + @Test + public void getOrDefaultTests(){ + List arr = ListUtilities.newArrayList("a", "b"); + assertEquals("a", getOrDefault(arr, 0, "z")); + assertEquals("b", getOrDefault(arr, 1, "z")); + assertEquals("z", getOrDefault(arr, 100, "z")); + assertEquals("z", getOrDefault(arr, -1, "z")); + + } +} diff --git a/waltz-common/src/test/java/org/finos/waltz/common/StreamUtilities_siphonTest.java b/waltz-common/src/test/java/org/finos/waltz/common/StreamUtilities_siphonTest.java new file mode 100644 index 0000000000..87669459e8 --- /dev/null +++ b/waltz-common/src/test/java/org/finos/waltz/common/StreamUtilities_siphonTest.java @@ -0,0 +1,32 @@ +package org.finos.waltz.common; + +import org.junit.jupiter.api.Test; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.finos.waltz.common.StreamUtilities.mkSiphon; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class StreamUtilities_siphonTest { + + @Test + public void siphon(){ + StreamUtilities.Siphon siphon = mkSiphon(x -> x.startsWith("h")); + + List result = Stream + .of("hello", "world", "happy", "earth", "hip", "hip", "hooray") + .filter(siphon) + .collect(Collectors.toList()); + + assertEquals(ListUtilities.asList("world", "earth"), result); + assertTrue(siphon.hasResults()); + assertEquals(ListUtilities.asList("hello", "happy", "hip", "hip", "hooray"), siphon.getResults()); + + } +}