@roomstay/frontend 2.6.32 → 2.6.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/166.bundle.js +1 -1
- package/dist/370.bundle.js +1 -1
- package/dist/449.bundle.js +1 -1
- package/dist/736.bundle.js +1 -1
- package/dist/903.bundle.js +1 -1
- package/dist/927.bundle.js +1 -1
- package/dist/e2e/canChangeCurrency.spec.d.ts +1 -0
- package/dist/e2e/canChangeCurrency.spec.js +59 -0
- package/dist/e2e/canChangeCurrency.spec.js.map +1 -0
- package/dist/e2e/canCheckout.spec.d.ts +1 -0
- package/dist/e2e/canCheckout.spec.js +205 -0
- package/dist/e2e/canCheckout.spec.js.map +1 -0
- package/dist/e2e/canViewFindReservationsPage.spec.d.ts +1 -0
- package/dist/e2e/canViewFindReservationsPage.spec.js +37 -0
- package/dist/e2e/canViewFindReservationsPage.spec.js.map +1 -0
- package/dist/e2e/canViewHotelnfoPage.spec.d.ts +1 -0
- package/dist/e2e/canViewHotelnfoPage.spec.js +42 -0
- package/dist/e2e/canViewHotelnfoPage.spec.js.map +1 -0
- package/dist/e2e/frontendTestConfigs.d.ts +7 -0
- package/dist/e2e/frontendTestConfigs.js +31 -0
- package/dist/e2e/frontendTestConfigs.js.map +1 -0
- package/dist/e2e/frontendTestData.d.ts +15 -0
- package/dist/e2e/frontendTestData.js +18 -0
- package/dist/e2e/frontendTestData.js.map +1 -0
- package/dist/e2e/goBackAndCheckoutAgain.spec.js +1 -0
- package/dist/e2e/goBackAndCheckoutAgain.spec.js.map +1 -1
- package/dist/e2e/helpers/playwrightHelpers.d.ts +2 -0
- package/dist/e2e/helpers/playwrightHelpers.js +27 -0
- package/dist/e2e/helpers/playwrightHelpers.js.map +1 -0
- package/dist/main.bundle.js +1 -1
- package/dist/src/api/AvailabilityAPI.d.ts +1 -1
- package/dist/src/api/AvailabilityAPI.js +2 -2
- package/dist/src/api/AvailabilityAPI.js.map +1 -1
- package/dist/src/api/HotelAPI.js +3 -0
- package/dist/src/api/HotelAPI.js.map +1 -1
- package/dist/src/components/generic/HtmlContentViewer.d.ts +3 -0
- package/dist/src/components/generic/HtmlContentViewer.js +41 -0
- package/dist/src/components/generic/HtmlContentViewer.js.map +1 -0
- package/dist/src/components/generic/Icon/Icon.d.ts +5 -93
- package/dist/src/components/generic/Icon/Icon.js +6 -124
- package/dist/src/components/generic/Icon/Icon.js.map +1 -1
- package/dist/src/components/generic/date/DatePicker.js +2 -2
- package/dist/src/components/generic/date/DatePicker.js.map +1 -1
- package/dist/src/components/generic/date/DatePickerDay.js +2 -2
- package/dist/src/components/generic/date/DatePickerDay.js.map +1 -1
- package/dist/src/components/members/SignInModal/InternalMemberSignInModal.js +1 -8
- package/dist/src/components/members/SignInModal/InternalMemberSignInModal.js.map +1 -1
- package/dist/src/components/members/SignInModal/MemberSignInModal.js +2 -2
- package/dist/src/components/members/SignInModal/MemberSignInModal.js.map +1 -1
- package/dist/src/components/steps/MinimumNightStayPill.js +2 -2
- package/dist/src/components/steps/MinimumNightStayPill.js.map +1 -1
- package/dist/src/components/steps/confirmation/RoomContactDetails.js +6 -6
- package/dist/src/components/steps/confirmation/RoomContactDetails.js.map +1 -1
- package/dist/src/components/steps/confirmation/StepConfirmationForm.js.map +1 -1
- package/dist/src/components/steps/confirmation/StepConfirmationPolicyBlock.js +3 -2
- package/dist/src/components/steps/confirmation/StepConfirmationPolicyBlock.js.map +1 -1
- package/dist/src/components/steps/date/PeoplePicker.js +5 -4
- package/dist/src/components/steps/date/PeoplePicker.js.map +1 -1
- package/dist/src/components/steps/date/StepDatePricePerRoom.js +2 -2
- package/dist/src/components/steps/date/StepDatePricePerRoom.js.map +1 -1
- package/dist/src/components/steps/hotel/HotelCard.js +8 -6
- package/dist/src/components/steps/hotel/HotelCard.js.map +1 -1
- package/dist/src/components/steps/hotel/HotelCardModal.js +8 -6
- package/dist/src/components/steps/hotel/HotelCardModal.js.map +1 -1
- package/dist/src/components/steps/hotel/HotelInfoPerksRow.js +3 -5
- package/dist/src/components/steps/hotel/HotelInfoPerksRow.js.map +1 -1
- package/dist/src/components/steps/room/AvailableUpgradesModal.js +3 -3
- package/dist/src/components/steps/room/AvailableUpgradesModal.js.map +1 -1
- package/dist/src/components/steps/room/LargeRoomCard.js +3 -1
- package/dist/src/components/steps/room/LargeRoomCard.js.map +1 -1
- package/dist/src/components/steps/room/NoRoomsFoundBlock.js +2 -2
- package/dist/src/components/steps/room/NoRoomsFoundBlock.js.map +1 -1
- package/dist/src/components/steps/room/RoomListCrossSellBlock.js +3 -3
- package/dist/src/components/steps/room/RoomListCrossSellBlock.js.map +1 -1
- package/dist/src/components/steps/room/RoomModalPerkRow.js +3 -5
- package/dist/src/components/steps/room/RoomModalPerkRow.js.map +1 -1
- package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummaryPromocodeInput.js +13 -2
- package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummaryPromocodeInput.js.map +1 -1
- package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummaryRow.js +4 -6
- package/dist/src/components/steps/room/UserSearchSummary/UserSearchSummaryRow.js.map +1 -1
- package/dist/src/components/steps/room/roomBuilderProgress/RoomBuilderProgressRow.js +11 -10
- package/dist/src/components/steps/room/roomBuilderProgress/RoomBuilderProgressRow.js.map +1 -1
- package/dist/src/components/steps/room/roomDetails/RoomDetails.js +1 -1
- package/dist/src/components/steps/room/roomDetails/RoomDetails.js.map +1 -1
- package/dist/src/components/steps/room/roomDetails/RoomDetailsPerkBlock.js +3 -2
- package/dist/src/components/steps/room/roomDetails/RoomDetailsPerkBlock.js.map +1 -1
- package/dist/src/components/steps/room/roomDetails/RoomDetailsRetargeting.js +3 -1
- package/dist/src/components/steps/room/roomDetails/RoomDetailsRetargeting.js.map +1 -1
- package/dist/src/components/steps/room/roomDetails/roomRates/RoomRateDescriptionTab.js +3 -2
- package/dist/src/components/steps/room/roomDetails/roomRates/RoomRateDescriptionTab.js.map +1 -1
- package/dist/src/components/summary/BEMobileSummaryModal.js +1 -1
- package/dist/src/components/summary/BEMobileSummaryModal.js.map +1 -1
- package/dist/src/components/summary/BESummary.js +1 -1
- package/dist/src/components/summary/BESummary.js.map +1 -1
- package/dist/src/components/summary/BESummaryPerkBlock.js +4 -3
- package/dist/src/components/summary/BESummaryPerkBlock.js.map +1 -1
- package/dist/src/components/summary/TransportDistanceFromHotelBlock.js +18 -11
- package/dist/src/components/summary/TransportDistanceFromHotelBlock.js.map +1 -1
- package/dist/src/contexts/BasketContext/BasketContextWrapper.js +18 -11
- package/dist/src/contexts/BasketContext/BasketContextWrapper.js.map +1 -1
- package/dist/src/contexts/CompanyContext/CompanyContextType.type.d.ts +0 -1
- package/dist/src/contexts/CompanyContext/CompanyContextType.type.js.map +1 -1
- package/dist/src/contexts/CompanyContext/CompanyContextWrapper.js +20 -12
- package/dist/src/contexts/CompanyContext/CompanyContextWrapper.js.map +1 -1
- package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepContextWrapper.js +5 -3
- package/dist/src/contexts/ConfirmationStepContext/ConfirmationStepContextWrapper.js.map +1 -1
- package/dist/src/engines/InlineRoomMiniEngine/InlineRoomMiniEngineElement.js +2 -2
- package/dist/src/engines/InlineRoomMiniEngine/InlineRoomMiniEngineElement.js.map +1 -1
- package/dist/src/hooks/RoomRateAvailabilityListFromApi.js +2 -2
- package/dist/src/hooks/RoomRateAvailabilityListFromApi.js.map +1 -1
- package/dist/src/hooks/useCalendarNightStay.js +2 -2
- package/dist/src/hooks/useCalendarNightStay.js.map +1 -1
- package/dist/src/hooks/useSignedInMember.d.ts +7 -0
- package/dist/src/hooks/{useExternalMember.js → useSignedInMember.js} +7 -5
- package/dist/src/hooks/useSignedInMember.js.map +1 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +3 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/models/Api/HotelDTO.d.ts +1 -1
- package/dist/src/models/Api/HotelDTO.js.map +1 -1
- package/dist/src/models/Api/ReservationsDTO.d.ts +1 -0
- package/dist/src/models/Api/ReservationsDTO.js.map +1 -1
- package/dist/src/models/BasketRow.d.ts +4 -1
- package/dist/src/models/BasketRow.js +15 -2
- package/dist/src/models/BasketRow.js.map +1 -1
- package/dist/src/models/Client/Hotel/Hotel.d.ts +4 -1
- package/dist/src/models/Client/Hotel/Hotel.js.map +1 -1
- package/dist/src/models/Client/Hotel/HotelPerk.d.ts +1 -1
- package/dist/src/models/Client/Hotel/HotelPerk.js.map +1 -1
- package/dist/src/pages/findReservation/FindReservationResults.js +22 -4
- package/dist/src/pages/findReservation/FindReservationResults.js.map +1 -1
- package/dist/src/pages/hotel/HotelInfo.js +2 -2
- package/dist/src/pages/hotel/HotelInfo.js.map +1 -1
- package/dist/src/translations/Translation.d.ts +9 -0
- package/dist/src/translations/Translation.js +9 -0
- package/dist/src/translations/Translation.js.map +1 -1
- package/dist/src/translations/languages/en-gb.js +9 -0
- package/dist/src/translations/languages/en-gb.js.map +1 -1
- package/dist/src/util/HotelPerkHelper.d.ts +3 -0
- package/dist/src/util/HotelPerkHelper.js +46 -0
- package/dist/src/util/HotelPerkHelper.js.map +1 -0
- package/dist/test.bundle.js +1 -1
- package/dist/vendors.bundle.js +1 -1
- package/dist/vendors.bundle.js.LICENSE.txt +2 -0
- package/package.json +6 -3
- package/dist/src/hooks/useExternalMember.d.ts +0 -5
- package/dist/src/hooks/useExternalMember.js.map +0 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const test_1 = require("@playwright/test");
|
|
13
|
+
const playwrightHelpers_1 = require("./helpers/playwrightHelpers");
|
|
14
|
+
(0, playwrightHelpers_1.runPlaywrightTestWithConfig)(runCanChangeCurrencyTets);
|
|
15
|
+
const currencies = [
|
|
16
|
+
'IDR - Indonesian Rupiahs',
|
|
17
|
+
'AUD - Australian Dollars',
|
|
18
|
+
'EUR - Euros',
|
|
19
|
+
];
|
|
20
|
+
const getNumericValueFromCurrencyString = (currencyString) => {
|
|
21
|
+
return parseFloat(currencyString.replace(/[^\d.]/g, ''));
|
|
22
|
+
};
|
|
23
|
+
function runCanChangeCurrencyTets(config) {
|
|
24
|
+
(0, test_1.test)(`can change currency on ${config.url}`, ({ page }) => __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
yield page.goto(config.url);
|
|
26
|
+
const currencySelector = page.locator('header.engine-header .be-select');
|
|
27
|
+
yield (0, test_1.expect)(currencySelector).toBeVisible();
|
|
28
|
+
const prices = {};
|
|
29
|
+
for (const currencyName of currencies) {
|
|
30
|
+
yield currencySelector.click();
|
|
31
|
+
const currencyOptions = page.locator('.rs-select--suggest-list');
|
|
32
|
+
yield (0, test_1.expect)(currencyOptions).toBeVisible();
|
|
33
|
+
const currencyOption = currencyOptions.locator(`text="${currencyName}"`);
|
|
34
|
+
yield (0, test_1.expect)(currencyOption).toBeVisible();
|
|
35
|
+
yield currencyOption.click();
|
|
36
|
+
// todo: Find a better way to check that the currency values are ready.
|
|
37
|
+
yield page.waitForTimeout(1000);
|
|
38
|
+
const firstAvailableDate = page.locator('.diji-calendar-month--item.--selectable').first();
|
|
39
|
+
const firstAvailableDatePriceElement = firstAvailableDate.locator('.diji-calendar-month--item-cost');
|
|
40
|
+
yield (0, test_1.expect)(firstAvailableDatePriceElement).not.toBeEmpty();
|
|
41
|
+
const price = yield firstAvailableDatePriceElement.textContent();
|
|
42
|
+
if (!price) {
|
|
43
|
+
console.error(`Failed to get price for currency: ${currencyName}`);
|
|
44
|
+
test_1.test.fail();
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
prices[currencyName] = price.trim();
|
|
48
|
+
console.log(`Currency: ${currencyName}, Price: ${price}`);
|
|
49
|
+
}
|
|
50
|
+
const idrValue = getNumericValueFromCurrencyString(prices['IDR - Indonesian Rupiahs']);
|
|
51
|
+
const eurValue = getNumericValueFromCurrencyString(prices['EUR - Euros']);
|
|
52
|
+
const audValue = getNumericValueFromCurrencyString(prices['AUD - Australian Dollars']);
|
|
53
|
+
// This assumes there's no drastic changes in currency rates!
|
|
54
|
+
(0, test_1.expect)(idrValue).toBeGreaterThan(audValue); // IDR > AUD
|
|
55
|
+
(0, test_1.expect)(audValue).toBeGreaterThan(eurValue); // AUD > EUR
|
|
56
|
+
}));
|
|
57
|
+
}
|
|
58
|
+
;
|
|
59
|
+
//# sourceMappingURL=canChangeCurrency.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canChangeCurrency.spec.js","sourceRoot":"/","sources":["e2e/canChangeCurrency.spec.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAgD;AAEhD,mEAA0E;AAE1E,IAAA,+CAA2B,EAAC,wBAAwB,CAAC,CAAC;AAEtD,MAAM,UAAU,GAAG;IACf,0BAA0B;IAC1B,0BAA0B;IAC1B,aAAa;CAChB,CAAC;AAEF,MAAM,iCAAiC,GAAG,CAAC,cAAsB,EAAU,EAAE;IACzE,OAAO,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;AAC7D,CAAC,CAAC;AAEF,SAAS,wBAAwB,CAAC,MAA0B;IACxD,IAAA,WAAI,EAAC,0BAA0B,MAAM,CAAC,GAAG,EAAE,EAAE,CAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QAC5D,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE5B,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACzE,MAAM,IAAA,aAAM,EAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;QAE7C,MAAM,MAAM,GAAmC,EAAE,CAAC;QAElD,KAAK,MAAM,YAAY,IAAI,UAAU,EAAE;YACnC,MAAM,gBAAgB,CAAC,KAAK,EAAE,CAAC;YAE/B,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;YACjE,MAAM,IAAA,aAAM,EAAC,eAAe,CAAC,CAAC,WAAW,EAAE,CAAC;YAE5C,MAAM,cAAc,GAAG,eAAe,CAAC,OAAO,CAAC,SAAS,YAAY,GAAG,CAAC,CAAC;YACzE,MAAM,IAAA,aAAM,EAAC,cAAc,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,cAAc,CAAC,KAAK,EAAE,CAAC;YAE7B,uEAAuE;YACvE,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAEhC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAAC,yCAAyC,CAAC,CAAC,KAAK,EAAE,CAAC;YAC3F,MAAM,8BAA8B,GAAG,kBAAkB,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;YAErG,MAAM,IAAA,aAAM,EAAC,8BAA8B,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YAE7D,MAAM,KAAK,GAAG,MAAM,8BAA8B,CAAC,WAAW,EAAE,CAAC;YAEjE,IAAI,CAAC,KAAK,EAAE;gBACR,OAAO,CAAC,KAAK,CAAC,qCAAqC,YAAY,EAAE,CAAC,CAAC;gBACnE,WAAI,CAAC,IAAI,EAAE,CAAC;gBACZ,OAAO;aACV;YAED,MAAM,CAAC,YAAY,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;YAEpC,OAAO,CAAC,GAAG,CAAC,aAAa,YAAY,YAAY,KAAK,EAAE,CAAC,CAAC;SAC7D;QAED,MAAM,QAAQ,GAAG,iCAAiC,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;QACvF,MAAM,QAAQ,GAAG,iCAAiC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAG,iCAAiC,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC;QAEvF,6DAA6D;QAC7D,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY;QACxD,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY;IAC5D,CAAC,CAAA,CAAC,CAAC;AACP,CAAC;AAAA,CAAC","sourcesContent":["import { test, expect } from '@playwright/test';\nimport { FrontendTestConfig } from './frontendTestConfigs';\nimport { runPlaywrightTestWithConfig } from './helpers/playwrightHelpers';\n\nrunPlaywrightTestWithConfig(runCanChangeCurrencyTets);\n\nconst currencies = [\n 'IDR - Indonesian Rupiahs',\n 'AUD - Australian Dollars',\n 'EUR - Euros',\n];\n\nconst getNumericValueFromCurrencyString = (currencyString: string): number => {\n return parseFloat(currencyString.replace(/[^\\d.]/g, ''));\n};\n\nfunction runCanChangeCurrencyTets(config: FrontendTestConfig) {\n test(`can change currency on ${config.url}`, async ({ page }) => {\n await page.goto(config.url);\n\n const currencySelector = page.locator('header.engine-header .be-select');\n await expect(currencySelector).toBeVisible();\n\n const prices: { [currency: string]: string } = {};\n\n for (const currencyName of currencies) {\n await currencySelector.click();\n\n const currencyOptions = page.locator('.rs-select--suggest-list');\n await expect(currencyOptions).toBeVisible();\n\n const currencyOption = currencyOptions.locator(`text=\"${currencyName}\"`);\n await expect(currencyOption).toBeVisible();\n await currencyOption.click();\n \n // todo: Find a better way to check that the currency values are ready.\n await page.waitForTimeout(1000);\n\n const firstAvailableDate = page.locator('.diji-calendar-month--item.--selectable').first();\n const firstAvailableDatePriceElement = firstAvailableDate.locator('.diji-calendar-month--item-cost');\n\n await expect(firstAvailableDatePriceElement).not.toBeEmpty();\n\n const price = await firstAvailableDatePriceElement.textContent();\n\n if (!price) {\n console.error(`Failed to get price for currency: ${currencyName}`);\n test.fail();\n return;\n }\n\n prices[currencyName] = price.trim();\n\n console.log(`Currency: ${currencyName}, Price: ${price}`);\n }\n\n const idrValue = getNumericValueFromCurrencyString(prices['IDR - Indonesian Rupiahs']);\n const eurValue = getNumericValueFromCurrencyString(prices['EUR - Euros']);\n const audValue = getNumericValueFromCurrencyString(prices['AUD - Australian Dollars']);\n \n // This assumes there's no drastic changes in currency rates!\n expect(idrValue).toBeGreaterThan(audValue); // IDR > AUD\n expect(audValue).toBeGreaterThan(eurValue); // AUD > EUR\n });\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const test_1 = require("@playwright/test");
|
|
13
|
+
const frontendTestData_1 = require("./frontendTestData");
|
|
14
|
+
const playwrightHelpers_1 = require("./helpers/playwrightHelpers");
|
|
15
|
+
(0, playwrightHelpers_1.runPlaywrightTestWithConfig)(runCanCheckoutTets);
|
|
16
|
+
function runCanCheckoutTets(config) {
|
|
17
|
+
(0, test_1.test)(`can checkout on ${config.url}`, ({ page }) => __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
// This test can take a while to complete if we need to check various different date ranges to find
|
|
19
|
+
// an available check-in and check-out date, so we need to increase the timeout.
|
|
20
|
+
test_1.test.setTimeout(120000); // 2 minutes.
|
|
21
|
+
yield page.goto(config.url);
|
|
22
|
+
let foundAvailableDates = false;
|
|
23
|
+
yield test_1.test.step('Select available dates', () => __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
foundAvailableDates = yield selectAvailableDates(page);
|
|
25
|
+
if (!foundAvailableDates) {
|
|
26
|
+
console.error('Unable to find available dates after maximum retries.');
|
|
27
|
+
test_1.test.fail();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
}));
|
|
31
|
+
yield test_1.test.step('Proceed to confirmation step', () => __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
yield proceedToConfirmationStep(page);
|
|
33
|
+
}));
|
|
34
|
+
if (!config.proceedWithPayment) {
|
|
35
|
+
console.log('Test completed up to the confirmation step.');
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.log('Continuing to payment step.');
|
|
40
|
+
}
|
|
41
|
+
yield test_1.test.step('Fill contact information', () => __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
yield fillContactInfo(page, frontendTestData_1.defaultCheckoutTestData);
|
|
43
|
+
}));
|
|
44
|
+
yield test_1.test.step('Fill payment information', () => __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
yield fillPaymentInformation(page, frontendTestData_1.defaultCheckoutTestData);
|
|
46
|
+
}));
|
|
47
|
+
yield test_1.test.step('Check Privacy Policy agreement', () => __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
// Locate the hidden checkbox using the label text
|
|
49
|
+
const hiddenCheckbox = page.locator('label:has-text("I have understood and agree to the Booking Conditions") input[type="checkbox"]');
|
|
50
|
+
// We can't click the actual checkbox because it's hidden (width and height of 0), so we need to find the
|
|
51
|
+
// fake checkbox and click that instead.
|
|
52
|
+
const fakeCheckbox = hiddenCheckbox.locator('~ span');
|
|
53
|
+
if ((yield fakeCheckbox.count()) === 0) {
|
|
54
|
+
console.log('Privacy Policy checkbox does not exist. Skipping step.');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
// Can't use the normal Playwright way of clicking something, I think it's because it's the ::before pseudo-element
|
|
58
|
+
// that's actually clickable.
|
|
59
|
+
yield fakeCheckbox.evaluate((element) => element.click());
|
|
60
|
+
}));
|
|
61
|
+
yield test_1.test.step('Submit the reservation', () => __awaiter(this, void 0, void 0, function* () {
|
|
62
|
+
const confirmReservationButton = page.getByRole('button', { name: 'Confirm Reservation' });
|
|
63
|
+
yield (0, test_1.expect)(confirmReservationButton).toBeVisible();
|
|
64
|
+
yield confirmReservationButton.click();
|
|
65
|
+
}));
|
|
66
|
+
yield test_1.test.step('Verify booking confirmation', () => __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
yield verifyBookingConfirmation(page, frontendTestData_1.defaultCheckoutTestData);
|
|
68
|
+
}));
|
|
69
|
+
yield page.waitForTimeout(1000);
|
|
70
|
+
}));
|
|
71
|
+
}
|
|
72
|
+
function selectAvailableDates(page, maxRetries = 5) {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
for (let attempt = 0; attempt < maxRetries; attempt++) {
|
|
75
|
+
// Choose the first available check-in date.
|
|
76
|
+
const checkInDateElement = page.locator('.diji-calendar-month--item.--selectable').first();
|
|
77
|
+
yield (0, test_1.expect)(checkInDateElement).toBeVisible();
|
|
78
|
+
yield checkInDateElement.click();
|
|
79
|
+
let checkOutDateElement;
|
|
80
|
+
if (attempt === maxRetries - 1) {
|
|
81
|
+
// If this is the last attempt, try a 1-night stay (this has a higher success rate).
|
|
82
|
+
checkOutDateElement = page.locator('.diji-calendar-month--item.--selectable:not(.--selected)').first();
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
// Choose a random available check-out date.
|
|
86
|
+
const checkOutDateElements = yield page.locator('.diji-calendar-month--item.--selectable:not(.--selected)').all();
|
|
87
|
+
const randomIndex = Math.floor(Math.random() * checkOutDateElements.length);
|
|
88
|
+
checkOutDateElement = checkOutDateElements[randomIndex];
|
|
89
|
+
}
|
|
90
|
+
yield (0, test_1.expect)(checkOutDateElement).toBeVisible();
|
|
91
|
+
yield checkOutDateElement.click();
|
|
92
|
+
// TODO: Instead of waiting for timeout, wait for the loading indicators on the other dates to disappear.
|
|
93
|
+
// Context: After choosing checkout date, the loading indicators appear for the dates following the checkout
|
|
94
|
+
// date. If we click 'Check Availability', we seem to briefly see an error message. This doesn't actually
|
|
95
|
+
// make the tests fail though. Keeping this in here in case it's indicative of an issue with RoomStay itself.
|
|
96
|
+
// The error is an "Oh no, something went wrong" message and shows the select room bar without any dates in it.
|
|
97
|
+
// The error quickly goes away though.
|
|
98
|
+
yield page.waitForTimeout(1000);
|
|
99
|
+
// Click the 'Check Availability' button.
|
|
100
|
+
const checkAvailabilityButton = page.getByRole('button', { name: 'Check Availability' });
|
|
101
|
+
yield (0, test_1.expect)(checkAvailabilityButton).not.toBeDisabled();
|
|
102
|
+
yield checkAvailabilityButton.click();
|
|
103
|
+
// Check for error message.
|
|
104
|
+
const errorMessage = yield page.waitForSelector('text=Please check your dates and', { timeout: 5000 }).catch(() => null);
|
|
105
|
+
if (errorMessage) {
|
|
106
|
+
console.log(`Error message found on attempt ${attempt + 1}. Retrying with different dates.`);
|
|
107
|
+
const newSearchButton = page.getByRole('button', { name: 'New Search' });
|
|
108
|
+
yield (0, test_1.expect)(newSearchButton).toBeVisible();
|
|
109
|
+
yield newSearchButton.click();
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return false;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function proceedToConfirmationStep(page) {
|
|
119
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
120
|
+
// Click the 'View Rates' button.
|
|
121
|
+
const viewRatesNowButton = page.getByRole('button', { name: 'View rates now' }).first();
|
|
122
|
+
yield (0, test_1.expect)(viewRatesNowButton).toBeVisible();
|
|
123
|
+
yield (0, test_1.expect)(viewRatesNowButton).not.toBeDisabled();
|
|
124
|
+
yield viewRatesNowButton.click();
|
|
125
|
+
// Click the first 'Book Now' button.
|
|
126
|
+
const firstBookNowButton = page.getByRole('button', { name: 'Book Now' }).first();
|
|
127
|
+
yield (0, test_1.expect)(firstBookNowButton).toBeVisible();
|
|
128
|
+
yield firstBookNowButton.click();
|
|
129
|
+
// Confirm that the 'Added xx' toast notification is visible.
|
|
130
|
+
const addedRoomNotification = page.locator('.c-notification__inner');
|
|
131
|
+
yield (0, test_1.expect)(addedRoomNotification).toBeVisible();
|
|
132
|
+
yield (0, test_1.expect)(addedRoomNotification).toContainText('Added');
|
|
133
|
+
// A bit hacky... Need a better way to check the current step.
|
|
134
|
+
try {
|
|
135
|
+
const isAddonsStep = yield page.waitForSelector('.step-selector__item.is-current p.text-body:has-text("Add-Ons")', { timeout: 1000 });
|
|
136
|
+
if (isAddonsStep) {
|
|
137
|
+
const nextButton = page.getByRole('button', { name: 'Next Step' }).first();
|
|
138
|
+
yield (0, test_1.expect)(nextButton).toBeVisible();
|
|
139
|
+
yield nextButton.click();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
console.log('Add-ons step not found, continuing.');
|
|
144
|
+
}
|
|
145
|
+
const confirmReservationButton = page.getByRole('button', { name: 'Confirm Reservation' });
|
|
146
|
+
yield (0, test_1.expect)(confirmReservationButton).toBeVisible();
|
|
147
|
+
yield (0, test_1.expect)(confirmReservationButton).toHaveText('Confirm Reservation');
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function fillContactInfo(page, data) {
|
|
151
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
// Fill Contact Info fields
|
|
153
|
+
yield page.fill('input[name="userProfiles.0.Forename"]', data.firstName);
|
|
154
|
+
yield page.fill('input[name="userProfiles.0.Surname"]', data.lastName);
|
|
155
|
+
yield page.fill('input[name="userProfiles.0.Email"]', data.email);
|
|
156
|
+
yield page.fill('input[name="userProfiles.0.Phone"]', data.phone);
|
|
157
|
+
yield page.fill('input[name="userProfiles.0.Address"]', data.address);
|
|
158
|
+
yield page.fill('input[name="userProfiles.0.City"]', data.city);
|
|
159
|
+
yield page.fill('input[name="userProfiles.0.PostCode"]', data.zipCode);
|
|
160
|
+
// Country selector
|
|
161
|
+
yield page.fill('.rs-enhanced-country-field--search input', data.country);
|
|
162
|
+
yield page.waitForSelector('.rs-enhanced-country-field--suggest-list-country', { state: 'visible' });
|
|
163
|
+
yield page.click('.rs-enhanced-country-field--suggest-list-country-name'); // Assuming there's only one result...
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
function fillPaymentInformation(page, data) {
|
|
167
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
168
|
+
// Fill Payment Information. Each of these fields is within their own secure iframe that we need to enter first.
|
|
169
|
+
const cardNumberFrame = yield (yield page.waitForSelector('iframe[title="Secure card number input frame"]')).contentFrame();
|
|
170
|
+
if (cardNumberFrame) {
|
|
171
|
+
yield cardNumberFrame.fill('input[aria-label="Card Number Input"]', data.cardNumber);
|
|
172
|
+
}
|
|
173
|
+
const cardExpiryFrame = yield (yield page.waitForSelector('iframe[title="Secure card expiration date input frame"]')).contentFrame();
|
|
174
|
+
if (cardExpiryFrame) {
|
|
175
|
+
yield cardExpiryFrame.fill('input[aria-label="Card expiration date"]', data.cardExpiry);
|
|
176
|
+
}
|
|
177
|
+
const cardCvvFrame = yield (yield page.waitForSelector('iframe[title="Secure card security code input frame"]')).contentFrame();
|
|
178
|
+
if (cardCvvFrame) {
|
|
179
|
+
yield cardCvvFrame.fill('input[aria-label="Card Security Code"]', data.cardCVC);
|
|
180
|
+
}
|
|
181
|
+
const cardNameFrame = yield (yield page.waitForSelector('iframe[title="Secure text input frame"]')).contentFrame();
|
|
182
|
+
if (cardNameFrame) {
|
|
183
|
+
yield cardNameFrame.fill('input[aria-label="Text input"]', `${data.firstName} ${data.lastName}`);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
function verifyBookingConfirmation(page, data) {
|
|
188
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
// We should now be on the 'Thanks' step.
|
|
190
|
+
yield page.waitForSelector('.step-selector__item.is-current p.text-body:has-text("Thanks")', { timeout: 3000 });
|
|
191
|
+
// There should be a message thanking us for our booking.
|
|
192
|
+
const thankYouMessage = page.locator('h3:has-text("Thank you")');
|
|
193
|
+
yield (0, test_1.expect)(thankYouMessage).toBeVisible();
|
|
194
|
+
// Click the 'More Details' button to show a modal with our booking details.
|
|
195
|
+
const moreDetailsButton = page.getByRole('button', { name: 'More Details' });
|
|
196
|
+
yield (0, test_1.expect)(moreDetailsButton).toBeVisible();
|
|
197
|
+
yield moreDetailsButton.click();
|
|
198
|
+
const modal = page.locator('div[class*="roomstay-modal"]').first();
|
|
199
|
+
yield (0, test_1.expect)(modal).toBeVisible();
|
|
200
|
+
// The modal should contain our name and email address.
|
|
201
|
+
yield (0, test_1.expect)(modal.locator(`text=${data.firstName} ${data.lastName}`)).toBeVisible();
|
|
202
|
+
yield (0, test_1.expect)(modal.locator(`text=${data.email}`)).toBeVisible();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=canCheckout.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canCheckout.spec.js","sourceRoot":"/","sources":["e2e/canCheckout.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect, Locator } from '@playwright/test';\nimport { FrontendTestConfig } from './frontendTestConfigs';\nimport { CheckoutTestData, defaultCheckoutTestData } from './frontendTestData';\nimport { runPlaywrightTestWithConfig } from './helpers/playwrightHelpers';\n\nrunPlaywrightTestWithConfig(runCanCheckoutTets);\n\nfunction runCanCheckoutTets(config: FrontendTestConfig) {\n test(`can checkout on ${config.url}`, async ({ page }) => {\n // This test can take a while to complete if we need to check various different date ranges to find\n // an available check-in and check-out date, so we need to increase the timeout.\n test.setTimeout(120000); // 2 minutes.\n await page.goto(config.url);\n\n let foundAvailableDates = false;\n\n await test.step('Select available dates', async () => {\n foundAvailableDates = await selectAvailableDates(page);\n if (!foundAvailableDates) {\n console.error('Unable to find available dates after maximum retries.');\n test.fail();\n return;\n }\n });\n\n await test.step('Proceed to confirmation step', async () => {\n await proceedToConfirmationStep(page);\n });\n\n if (!config.proceedWithPayment) {\n console.log('Test completed up to the confirmation step.');\n return;\n } else {\n console.log('Continuing to payment step.');\n }\n\n await test.step('Fill contact information', async () => {\n await fillContactInfo(page, defaultCheckoutTestData);\n });\n\n await test.step('Fill payment information', async () => {\n await fillPaymentInformation(page, defaultCheckoutTestData);\n });\n\n await test.step('Check Privacy Policy agreement', async () => {\n // Locate the hidden checkbox using the label text\n const hiddenCheckbox = page.locator('label:has-text(\"I have understood and agree to the Booking Conditions\") input[type=\"checkbox\"]');\n\n // We can't click the actual checkbox because it's hidden (width and height of 0), so we need to find the\n // fake checkbox and click that instead.\n const fakeCheckbox = hiddenCheckbox.locator('~ span');\n if ((await fakeCheckbox.count()) === 0) {\n console.log('Privacy Policy checkbox does not exist. Skipping step.');\n return;\n }\n\n // Can't use the normal Playwright way of clicking something, I think it's because it's the ::before pseudo-element\n // that's actually clickable.\n await fakeCheckbox.evaluate((element: HTMLElement) => element.click());\n });\n\n await test.step('Submit the reservation', async () => {\n const confirmReservationButton = page.getByRole('button', { name: 'Confirm Reservation' });\n await expect(confirmReservationButton).toBeVisible();\n await confirmReservationButton.click();\n });\n\n await test.step('Verify booking confirmation', async () => {\n await verifyBookingConfirmation(page, defaultCheckoutTestData);\n });\n\n await page.waitForTimeout(1000);\n });\n}\n\nasync function selectAvailableDates(page: any, maxRetries: number = 5): Promise<boolean> {\n for (let attempt = 0; attempt < maxRetries; attempt++) {\n // Choose the first available check-in date.\n const checkInDateElement = page.locator('.diji-calendar-month--item.--selectable').first();\n await expect(checkInDateElement).toBeVisible();\n await checkInDateElement.click();\n\n let checkOutDateElement: Locator;\n if (attempt === maxRetries - 1) {\n // If this is the last attempt, try a 1-night stay (this has a higher success rate).\n checkOutDateElement = page.locator('.diji-calendar-month--item.--selectable:not(.--selected)').first();\n } else {\n // Choose a random available check-out date.\n const checkOutDateElements = await page.locator('.diji-calendar-month--item.--selectable:not(.--selected)').all();\n const randomIndex = Math.floor(Math.random() * checkOutDateElements.length);\n checkOutDateElement = checkOutDateElements[randomIndex];\n }\n\n await expect(checkOutDateElement).toBeVisible();\n await checkOutDateElement.click();\n\n // TODO: Instead of waiting for timeout, wait for the loading indicators on the other dates to disappear.\n // Context: After choosing checkout date, the loading indicators appear for the dates following the checkout\n // date. If we click 'Check Availability', we seem to briefly see an error message. This doesn't actually\n // make the tests fail though. Keeping this in here in case it's indicative of an issue with RoomStay itself.\n // The error is an \"Oh no, something went wrong\" message and shows the select room bar without any dates in it.\n // The error quickly goes away though.\n await page.waitForTimeout(1000);\n\n // Click the 'Check Availability' button.\n const checkAvailabilityButton = page.getByRole('button', { name: 'Check Availability' });\n await expect(checkAvailabilityButton).not.toBeDisabled();\n await checkAvailabilityButton.click();\n\n // Check for error message.\n const errorMessage = await page.waitForSelector('text=Please check your dates and', { timeout: 5000 }).catch(() => null);\n if (errorMessage) {\n console.log(`Error message found on attempt ${attempt + 1}. Retrying with different dates.`);\n const newSearchButton = page.getByRole('button', { name: 'New Search' });\n await expect(newSearchButton).toBeVisible();\n await newSearchButton.click();\n } else {\n return true;\n }\n }\n return false;\n}\n\nasync function proceedToConfirmationStep(page: any) {\n // Click the 'View Rates' button.\n const viewRatesNowButton = page.getByRole('button', { name: 'View rates now' }).first();\n await expect(viewRatesNowButton).toBeVisible();\n await expect(viewRatesNowButton).not.toBeDisabled();\n await viewRatesNowButton.click();\n\n // Click the first 'Book Now' button.\n const firstBookNowButton = page.getByRole('button', { name: 'Book Now' }).first();\n await expect(firstBookNowButton).toBeVisible();\n await firstBookNowButton.click();\n\n // Confirm that the 'Added xx' toast notification is visible.\n const addedRoomNotification = page.locator('.c-notification__inner');\n await expect(addedRoomNotification).toBeVisible();\n await expect(addedRoomNotification).toContainText('Added');\n\n // A bit hacky... Need a better way to check the current step.\n try {\n const isAddonsStep = await page.waitForSelector('.step-selector__item.is-current p.text-body:has-text(\"Add-Ons\")', { timeout: 1000 });\n if (isAddonsStep) {\n const nextButton = page.getByRole('button', { name: 'Next Step' }).first();\n await expect(nextButton).toBeVisible();\n await nextButton.click();\n }\n } catch (error) {\n console.log('Add-ons step not found, continuing.');\n }\n\n const confirmReservationButton = page.getByRole('button', { name: 'Confirm Reservation' });\n await expect(confirmReservationButton).toBeVisible();\n await expect(confirmReservationButton).toHaveText('Confirm Reservation');\n}\n\nasync function fillContactInfo(page: any, data: CheckoutTestData) {\n // Fill Contact Info fields\n await page.fill('input[name=\"userProfiles.0.Forename\"]', data.firstName);\n await page.fill('input[name=\"userProfiles.0.Surname\"]', data.lastName);\n await page.fill('input[name=\"userProfiles.0.Email\"]', data.email);\n await page.fill('input[name=\"userProfiles.0.Phone\"]', data.phone);\n await page.fill('input[name=\"userProfiles.0.Address\"]', data.address);\n await page.fill('input[name=\"userProfiles.0.City\"]', data.city);\n await page.fill('input[name=\"userProfiles.0.PostCode\"]', data.zipCode);\n\n // Country selector\n await page.fill('.rs-enhanced-country-field--search input', data.country);\n await page.waitForSelector('.rs-enhanced-country-field--suggest-list-country', { state: 'visible' });\n await page.click('.rs-enhanced-country-field--suggest-list-country-name'); // Assuming there's only one result...\n}\n\nasync function fillPaymentInformation(page: any, data: CheckoutTestData) {\n // Fill Payment Information. Each of these fields is within their own secure iframe that we need to enter first.\n\n const cardNumberFrame = await (await page.waitForSelector('iframe[title=\"Secure card number input frame\"]')).contentFrame();\n if (cardNumberFrame) {\n await cardNumberFrame.fill('input[aria-label=\"Card Number Input\"]', data.cardNumber);\n }\n\n const cardExpiryFrame = await (await page.waitForSelector('iframe[title=\"Secure card expiration date input frame\"]')).contentFrame();\n if (cardExpiryFrame) {\n await cardExpiryFrame.fill('input[aria-label=\"Card expiration date\"]', data.cardExpiry);\n }\n\n const cardCvvFrame = await (await page.waitForSelector('iframe[title=\"Secure card security code input frame\"]')).contentFrame();\n if (cardCvvFrame) {\n await cardCvvFrame.fill('input[aria-label=\"Card Security Code\"]', data.cardCVC);\n }\n\n const cardNameFrame = await (await page.waitForSelector('iframe[title=\"Secure text input frame\"]')).contentFrame();\n if (cardNameFrame) {\n await cardNameFrame.fill('input[aria-label=\"Text input\"]', `${data.firstName} ${data.lastName}`);\n }\n}\n\nasync function verifyBookingConfirmation(page: any, data: CheckoutTestData) {\n // We should now be on the 'Thanks' step.\n await page.waitForSelector('.step-selector__item.is-current p.text-body:has-text(\"Thanks\")', { timeout: 3000 });\n\n // There should be a message thanking us for our booking.\n const thankYouMessage = page.locator('h3:has-text(\"Thank you\")');\n await expect(thankYouMessage).toBeVisible();\n\n // Click the 'More Details' button to show a modal with our booking details.\n const moreDetailsButton = page.getByRole('button', { name: 'More Details' });\n await expect(moreDetailsButton).toBeVisible();\n await moreDetailsButton.click();\n\n const modal = page.locator('div[class*=\"roomstay-modal\"]').first();\n await expect(modal).toBeVisible();\n\n // The modal should contain our name and email address.\n await expect(modal.locator(`text=${data.firstName} ${data.lastName}`)).toBeVisible();\n await expect(modal.locator(`text=${data.email}`)).toBeVisible();\n}"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const test_1 = require("@playwright/test");
|
|
13
|
+
const playwrightHelpers_1 = require("./helpers/playwrightHelpers");
|
|
14
|
+
(0, playwrightHelpers_1.runPlaywrightTestWithConfig)(runCanViewReservationsPageTest);
|
|
15
|
+
function runCanViewReservationsPageTest(config) {
|
|
16
|
+
(0, test_1.test)(`can view find reservations page on ${config.url}`, ({ page }) => __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
yield page.goto(config.url);
|
|
18
|
+
// Click through to the 'Hotel info' page.
|
|
19
|
+
const findReservationsLink = page.getByRole('link', { name: 'Find reservations' });
|
|
20
|
+
yield (0, test_1.expect)(findReservationsLink).toBeVisible();
|
|
21
|
+
yield findReservationsLink.click();
|
|
22
|
+
// Verify that the expected elements are on the page.
|
|
23
|
+
const findYourReservationHeading = page.getByRole('heading', { name: 'Find your reservation' });
|
|
24
|
+
yield (0, test_1.expect)(findYourReservationHeading).toBeVisible();
|
|
25
|
+
const findReservationButton = page.getByRole('button', { name: 'Find Reservation' });
|
|
26
|
+
yield (0, test_1.expect)(findReservationButton).toBeVisible();
|
|
27
|
+
// todo: Maybe test form validation?
|
|
28
|
+
// Verify that we can go back to the main booking page.
|
|
29
|
+
const backToCheckAvailabilityButton = page.getByRole('button', { name: 'Back to check availability' });
|
|
30
|
+
yield (0, test_1.expect)(backToCheckAvailabilityButton).toBeVisible();
|
|
31
|
+
yield backToCheckAvailabilityButton.click();
|
|
32
|
+
const selectYourDateHeading = page.getByRole('heading', { name: 'Select your date' });
|
|
33
|
+
yield (0, test_1.expect)(selectYourDateHeading).toBeVisible();
|
|
34
|
+
}));
|
|
35
|
+
}
|
|
36
|
+
;
|
|
37
|
+
//# sourceMappingURL=canViewFindReservationsPage.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canViewFindReservationsPage.spec.js","sourceRoot":"/","sources":["e2e/canViewFindReservationsPage.spec.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAgD;AAEhD,mEAA0E;AAE1E,IAAA,+CAA2B,EAAC,8BAA8B,CAAC,CAAC;AAE5D,SAAS,8BAA8B,CAAC,MAA0B;IAC9D,IAAA,WAAI,EAAC,sCAAsC,MAAM,CAAC,GAAG,EAAE,EAAE,CAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QACxE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE5B,0CAA0C;QAC1C,MAAM,oBAAoB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACnF,MAAM,IAAA,aAAM,EAAC,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAC;QACjD,MAAM,oBAAoB,CAAC,KAAK,EAAE,CAAC;QAEnC,qDAAqD;QACrD,MAAM,0BAA0B,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAChG,MAAM,IAAA,aAAM,EAAC,0BAA0B,CAAC,CAAC,WAAW,EAAE,CAAC;QAEvD,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACrF,MAAM,IAAA,aAAM,EAAC,qBAAqB,CAAC,CAAC,WAAW,EAAE,CAAC;QAElD,oCAAoC;QAEpC,uDAAuD;QACvD,MAAM,6BAA6B,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,4BAA4B,EAAE,CAAC,CAAC;QACvG,MAAM,IAAA,aAAM,EAAC,6BAA6B,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1D,MAAM,6BAA6B,CAAC,KAAK,EAAE,CAAC;QAC5C,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACtF,MAAM,IAAA,aAAM,EAAC,qBAAqB,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC,CAAA,CAAC,CAAC;AACP,CAAC;AAAA,CAAC","sourcesContent":["import { test, expect } from '@playwright/test';\nimport { FrontendTestConfig } from './frontendTestConfigs';\nimport { runPlaywrightTestWithConfig } from './helpers/playwrightHelpers';\n\nrunPlaywrightTestWithConfig(runCanViewReservationsPageTest);\n\nfunction runCanViewReservationsPageTest(config: FrontendTestConfig) {\n test(`can view find reservations page on ${config.url}`, async ({ page }) => {\n await page.goto(config.url);\n\n // Click through to the 'Hotel info' page.\n const findReservationsLink = page.getByRole('link', { name: 'Find reservations' });\n await expect(findReservationsLink).toBeVisible();\n await findReservationsLink.click();\n \n // Verify that the expected elements are on the page.\n const findYourReservationHeading = page.getByRole('heading', { name: 'Find your reservation' });\n await expect(findYourReservationHeading).toBeVisible();\n \n const findReservationButton = page.getByRole('button', { name: 'Find Reservation' });\n await expect(findReservationButton).toBeVisible();\n \n // todo: Maybe test form validation?\n \n // Verify that we can go back to the main booking page.\n const backToCheckAvailabilityButton = page.getByRole('button', { name: 'Back to check availability' });\n await expect(backToCheckAvailabilityButton).toBeVisible();\n await backToCheckAvailabilityButton.click();\n const selectYourDateHeading = page.getByRole('heading', { name: 'Select your date' });\n await expect(selectYourDateHeading).toBeVisible();\n });\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const test_1 = require("@playwright/test");
|
|
13
|
+
const playwrightHelpers_1 = require("./helpers/playwrightHelpers");
|
|
14
|
+
(0, playwrightHelpers_1.runPlaywrightTestWithConfig)(runCanViewHotelInfoPageTest);
|
|
15
|
+
function runCanViewHotelInfoPageTest(config) {
|
|
16
|
+
(0, test_1.test)(`can view hotel info on ${config.url}`, ({ page }) => __awaiter(this, void 0, void 0, function* () {
|
|
17
|
+
yield page.goto(config.url);
|
|
18
|
+
// Click through to the 'Hotel info' page.
|
|
19
|
+
const hotelInfoLink = page.getByRole('link', { name: 'Hotel info' });
|
|
20
|
+
yield (0, test_1.expect)(hotelInfoLink).toBeVisible();
|
|
21
|
+
yield hotelInfoLink.click();
|
|
22
|
+
// Check that header and subheader are on the page.
|
|
23
|
+
const header = page.locator('h1.c-masthead__header');
|
|
24
|
+
const subheader = page.locator('h2.c-masthead__sub-header');
|
|
25
|
+
(0, test_1.expect)(header).toBeVisible();
|
|
26
|
+
(0, test_1.expect)(header).not.toBeEmpty();
|
|
27
|
+
(0, test_1.expect)(subheader).toBeVisible();
|
|
28
|
+
(0, test_1.expect)(subheader).not.toBeEmpty();
|
|
29
|
+
// Check that the 'Powered by roomstay.io' message exists.
|
|
30
|
+
const poweredByMessage = page.getByText('Powered by Roomstay.io');
|
|
31
|
+
yield (0, test_1.expect)(poweredByMessage).toBeVisible();
|
|
32
|
+
// Check that the 'Book Now' button exists.
|
|
33
|
+
const bookNowButton = page.getByRole('button', { name: 'Book Now' });
|
|
34
|
+
(0, test_1.expect)(bookNowButton).toBeVisible();
|
|
35
|
+
// Check that clicking the 'Book Now' button takes the user to the booking page.
|
|
36
|
+
yield bookNowButton.click();
|
|
37
|
+
const selectYourDateHeading = page.getByRole('heading', { name: 'Select your date' });
|
|
38
|
+
yield (0, test_1.expect)(selectYourDateHeading).toBeVisible();
|
|
39
|
+
}));
|
|
40
|
+
}
|
|
41
|
+
;
|
|
42
|
+
//# sourceMappingURL=canViewHotelnfoPage.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canViewHotelnfoPage.spec.js","sourceRoot":"/","sources":["e2e/canViewHotelnfoPage.spec.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAgD;AAEhD,mEAA0E;AAE1E,IAAA,+CAA2B,EAAC,2BAA2B,CAAC,CAAC;AAEzD,SAAS,2BAA2B,CAAC,MAA0B;IAC3D,IAAA,WAAI,EAAC,0BAA0B,MAAM,CAAC,GAAG,EAAE,EAAE,CAAO,EAAE,IAAI,EAAE,EAAE,EAAE;QAC5D,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAE5B,0CAA0C;QAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QACrE,MAAM,IAAA,aAAM,EAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC;QAE5B,mDAAmD;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,2BAA2B,CAAC,CAAC;QAC5D,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC7B,IAAA,aAAM,EAAC,MAAM,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QAC/B,IAAA,aAAM,EAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QAChC,IAAA,aAAM,EAAC,SAAS,CAAC,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;QAElC,0DAA0D;QAC1D,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;QAClE,MAAM,IAAA,aAAM,EAAC,gBAAgB,CAAC,CAAC,WAAW,EAAE,CAAC;QAE7C,2CAA2C;QAC3C,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;QACrE,IAAA,aAAM,EAAC,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;QAEpC,gFAAgF;QAChF,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC;QAC5B,MAAM,qBAAqB,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,CAAC,CAAC;QACtF,MAAM,IAAA,aAAM,EAAC,qBAAqB,CAAC,CAAC,WAAW,EAAE,CAAC;IACtD,CAAC,CAAA,CAAC,CAAC;AACP,CAAC;AAAA,CAAC","sourcesContent":["import { test, expect } from '@playwright/test';\nimport { FrontendTestConfig, testConfigs } from './frontendTestConfigs';\nimport { runPlaywrightTestWithConfig } from './helpers/playwrightHelpers';\n\nrunPlaywrightTestWithConfig(runCanViewHotelInfoPageTest);\n\nfunction runCanViewHotelInfoPageTest(config: FrontendTestConfig) {\n test(`can view hotel info on ${config.url}`, async ({ page }) => {\n await page.goto(config.url);\n\n // Click through to the 'Hotel info' page.\n const hotelInfoLink = page.getByRole('link', { name: 'Hotel info' });\n await expect(hotelInfoLink).toBeVisible();\n await hotelInfoLink.click();\n \n // Check that header and subheader are on the page.\n const header = page.locator('h1.c-masthead__header');\n const subheader = page.locator('h2.c-masthead__sub-header');\n expect(header).toBeVisible();\n expect(header).not.toBeEmpty();\n expect(subheader).toBeVisible();\n expect(subheader).not.toBeEmpty();\n \n // Check that the 'Powered by roomstay.io' message exists.\n const poweredByMessage = page.getByText('Powered by Roomstay.io');\n await expect(poweredByMessage).toBeVisible();\n \n // Check that the 'Book Now' button exists.\n const bookNowButton = page.getByRole('button', { name: 'Book Now' });\n expect(bookNowButton).toBeVisible();\n \n // Check that clicking the 'Book Now' button takes the user to the booking page.\n await bookNowButton.click();\n const selectYourDateHeading = page.getByRole('heading', { name: 'Select your date' });\n await expect(selectYourDateHeading).toBeVisible();\n });\n};\n"]}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.testConfigs = void 0;
|
|
4
|
+
exports.testConfigs = [
|
|
5
|
+
{
|
|
6
|
+
url: 'http://localhost:9000/',
|
|
7
|
+
proceedWithPayment: true,
|
|
8
|
+
runByDefault: true,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
url: 'http://localhost:9003/CrystalBrook-Bailey-index.html',
|
|
12
|
+
proceedWithPayment: false,
|
|
13
|
+
isClient: true,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
url: 'http://localhost:9003/Ovolo-Central-index.html',
|
|
17
|
+
proceedWithPayment: false,
|
|
18
|
+
isClient: true,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
url: 'http://localhost:9003/Ovolo-Laneways-index.html',
|
|
22
|
+
proceedWithPayment: false,
|
|
23
|
+
isClient: true,
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
url: 'http://localhost:9003/CrystalBrook-Albion-index.html',
|
|
27
|
+
proceedWithPayment: false,
|
|
28
|
+
isClient: true,
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
//# sourceMappingURL=frontendTestConfigs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontendTestConfigs.js","sourceRoot":"/","sources":["e2e/frontendTestConfigs.ts"],"names":[],"mappings":";;;AAMa,QAAA,WAAW,GAAyB;IAC7C;QACI,GAAG,EAAE,wBAAwB;QAC7B,kBAAkB,EAAE,IAAI;QACxB,YAAY,EAAE,IAAI;KACrB;IACD;QACI,GAAG,EAAE,sDAAsD;QAC3D,kBAAkB,EAAE,KAAK;QACzB,QAAQ,EAAE,IAAI;KACjB;IACD;QACI,GAAG,EAAE,gDAAgD;QACrD,kBAAkB,EAAE,KAAK;QACzB,QAAQ,EAAE,IAAI;KACjB;IACD;QACI,GAAG,EAAE,iDAAiD;QACtD,kBAAkB,EAAE,KAAK;QACzB,QAAQ,EAAE,IAAI;KACjB;IACD;QACI,GAAG,EAAE,sDAAsD;QAC3D,kBAAkB,EAAE,KAAK;QACzB,QAAQ,EAAE,IAAI;KACjB;CACJ,CAAC","sourcesContent":["export interface FrontendTestConfig {\n url: string; proceedWithPayment: boolean;\n isClient?: boolean;\n runByDefault?: boolean;\n}\n\nexport const testConfigs: FrontendTestConfig[] = [\n {\n url: 'http://localhost:9000/',\n proceedWithPayment: true,\n runByDefault: true,\n },\n {\n url: 'http://localhost:9003/CrystalBrook-Bailey-index.html',\n proceedWithPayment: false,\n isClient: true,\n },\n {\n url: 'http://localhost:9003/Ovolo-Central-index.html',\n proceedWithPayment: false,\n isClient: true,\n },\n {\n url: 'http://localhost:9003/Ovolo-Laneways-index.html',\n proceedWithPayment: false,\n isClient: true,\n },\n {\n url: 'http://localhost:9003/CrystalBrook-Albion-index.html',\n proceedWithPayment: false, \n isClient: true,\n }\n];"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface CheckoutTestData {
|
|
2
|
+
firstName: string;
|
|
3
|
+
lastName: string;
|
|
4
|
+
email: string;
|
|
5
|
+
phone: string;
|
|
6
|
+
address: string;
|
|
7
|
+
city: string;
|
|
8
|
+
state: string;
|
|
9
|
+
zipCode: string;
|
|
10
|
+
country: string;
|
|
11
|
+
cardNumber: string;
|
|
12
|
+
cardExpiry: string;
|
|
13
|
+
cardCVC: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const defaultCheckoutTestData: CheckoutTestData;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultCheckoutTestData = void 0;
|
|
4
|
+
exports.defaultCheckoutTestData = {
|
|
5
|
+
firstName: 'Test',
|
|
6
|
+
lastName: 'User',
|
|
7
|
+
email: 'test.user@example.com',
|
|
8
|
+
phone: '+1234567890',
|
|
9
|
+
address: '123 Main St',
|
|
10
|
+
city: 'Testcity',
|
|
11
|
+
state: 'State',
|
|
12
|
+
zipCode: '12345',
|
|
13
|
+
country: 'Australia',
|
|
14
|
+
cardNumber: '4242 4242 4242 4242',
|
|
15
|
+
cardExpiry: '12/30',
|
|
16
|
+
cardCVC: '123',
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=frontendTestData.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frontendTestData.js","sourceRoot":"/","sources":["e2e/frontendTestData.ts"],"names":[],"mappings":";;;AAea,QAAA,uBAAuB,GAAqB;IACrD,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;IAChB,KAAK,EAAE,uBAAuB;IAC9B,KAAK,EAAE,aAAa;IACpB,OAAO,EAAE,aAAa;IACtB,IAAI,EAAE,UAAU;IAChB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,OAAO;IAChB,OAAO,EAAE,WAAW;IACpB,UAAU,EAAE,qBAAqB;IACjC,UAAU,EAAE,OAAO;IACnB,OAAO,EAAE,KAAK;CACjB,CAAC","sourcesContent":["export interface CheckoutTestData {\n firstName: string;\n lastName: string;\n email: string;\n phone: string;\n address: string;\n city: string;\n state: string;\n zipCode: string;\n country: string;\n cardNumber: string;\n cardExpiry: string;\n cardCVC: string;\n}\n\nexport const defaultCheckoutTestData: CheckoutTestData = {\n firstName: 'Test',\n lastName: 'User',\n email: 'test.user@example.com',\n phone: '+1234567890',\n address: '123 Main St',\n city: 'Testcity',\n state: 'State',\n zipCode: '12345',\n country: 'Australia',\n cardNumber: '4242 4242 4242 4242',\n cardExpiry: '12/30',\n cardCVC: '123',\n};\n"]}
|
|
@@ -12,6 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
12
12
|
const test_1 = require("@playwright/test");
|
|
13
13
|
const checkoutHelpers_1 = require("./helpers/checkoutHelpers");
|
|
14
14
|
const checkoutTestData_1 = require("./data/checkoutTestData");
|
|
15
|
+
// This test just runs on the Frontend Demo, as it needs to actually be able to check out with fake payment details.
|
|
15
16
|
const url = 'http://localhost:9000/';
|
|
16
17
|
(0, test_1.test)(`can checkout on ${url}, and then go back and checkout again.`, ({ page }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
18
|
// This test can take a while to complete if we need to check various different date ranges to find
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"goBackAndCheckoutAgain.spec.js","sourceRoot":"/","sources":["e2e/goBackAndCheckoutAgain.spec.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,2CAAgD;AAChD,+DAA0L;AAC1L,8DAA6F;AAE7F,MAAM,GAAG,GAAG,wBAAwB,CAAC;AAErC,IAAA,WAAI,EAAC,mBAAmB,GAAG,wCAAwC,EAAE,CAAO,EAAE,IAAI,EAAE,EAAE,EAAE;IACpF,mGAAmG;IACnG,gFAAgF;IAChF,WAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY;IACpC,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAErB,MAAM,WAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAS,EAAE;QACjD,MAAM,mBAAmB,GAAG,MAAM,IAAA,sCAAoB,EAAC,IAAI,CAAC,CAAC;QAC7D,IAAI,CAAC,mBAAmB,EAAE;YACtB,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;YACvE,WAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO;SACV;IACL,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,WAAI,CAAC,IAAI,CAAC,8BAA8B,EAAE,GAAS,EAAE;QACvD,MAAM,IAAA,2CAAyB,EAAC,IAAI,CAAC,CAAC;IAC1C,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,WAAI,CAAC,IAAI,CAAC,sCAAsC,EAAE,GAAS,EAAE;QAC/D,MAAM,IAAA,iCAAe,EAAC,IAAI,EAAE,0CAAuB,CAAC,CAAC;QACrD,MAAM,IAAA,wCAAsB,EAAC,IAAI,EAAE,0CAAuB,CAAC,CAAC;IAChE,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,WAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,GAAS,EAAE;QACjD,MAAM,IAAA,0CAAwB,EAAC,IAAI,CAAC,CAAC;IACzC,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,WAAI,CAAC,IAAI,CAAC,6BAA6B,EAAE,GAAS,EAAE;QACtD,MAAM,IAAA,2CAAyB,EAAC,IAAI,EAAE,0CAAuB,CAAC,CAAC;IACnE,CAAC,CAAA,CAAC,CAAC;IAEH,2FAA2F;IAC3F,MAAM,WAAI,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAS,EAAE;QAChE,gGAAgG;QAChG,wCAAwC;QACxC,MAAM,oBAAoB,GAAG,IAAI,CAAC,OAAO,CAAC,2DAA2D,CAAC,CAAC;QACvG,MAAM,IAAA,aAAM,EAAC,oBAAoB,CAAC,CAAC,WAAW,EAAE,CAAC;QACjD,MAAM,oBAAoB,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,+DAA+D;QAElH,uDAAuD;QACvD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,iCAAiC,CAAC,CAAC;QACpE,MAAM,IAAA,aAAM,EAAC,WAAW,CAAC,CAAC,aAAa,CAAC,sBAAsB,CAAC,CAAC;IACpE,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,WAAI,CAAC,IAAI,CAAC,kEAAkE,EAAE,GAAS,EAAE;QAC3F,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,0DAA0D,CAAC,CAAC;QACrG,MAAM,gBAAgB,GAAG,mBAAmB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAE1D,2DAA2D;QAC3D,MAAM,WAAW,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,EAAE;YAC/D,OAAO,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,IAAA,aAAM,EAAC,WAAW,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAExC,oCAAoC;QACpC,MAAM,IAAA,aAAM,EAAC,gBAAgB,CAAC,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;IACrD,CAAC,CAAA,CAAC,CAAC;IAEH,MAAM,WAAI,CAAC,IAAI,CAAC,+EAA+E,EAAE,GAAS,EAAE;QACxG,MAAM,IAAA,2CAAyB,EAAC,IAAI,CAAC,CAAC;QACtC,MAAM,IAAA,iCAAe,EAAC,IAAI,EAAE,4CAAyB,CAAC,CAAC;QACvD,MAAM,IAAA,wCAAsB,EAAC,IAAI,EAAE,4CAAyB,CAAC,CAAC;QAC9D,MAAM,IAAA,0CAAwB,EAAC,IAAI,CAAC,CAAC;QACrC,MAAM,IAAA,2CAAyB,EAAC,IAAI,EAAE,4CAAyB,CAAC,CAAC;IACrE,CAAC,CAAA,CAAC,CAAC;AACP,CAAC,CAAA,CAAC,CAAC","sourcesContent":["import { test, expect } from '@playwright/test';\nimport { fillContactInfo, fillPaymentInformation, proceedToConfirmationStep, selectAvailableDates, submitBookingReservation, verifyBookingConfirmation } from './helpers/checkoutHelpers';\nimport { checkoutTestDataDefault, checkoutTestDataSecondary } from './data/checkoutTestData';\n\nconst url = 'http://localhost:9000/';\n\ntest(`can checkout on ${url}, and then go back and checkout again.`, async ({ page }) => {\n // This test can take a while to complete if we need to check various different date ranges to find\n // an available check-in and check-out date, so we need to increase the timeout.\n test.setTimeout(60000); // 1 minute.\n await page.goto(url);\n\n await test.step('Select available dates', async () => {\n const foundAvailableDates = await selectAvailableDates(page);\n if (!foundAvailableDates) {\n console.error('Unable to find available dates after maximum retries.');\n test.fail();\n return;\n }\n });\n\n await test.step('Proceed to confirmation step', async () => {\n await proceedToConfirmationStep(page);\n });\n\n await test.step('Fill contact and payment information', async () => {\n await fillContactInfo(page, checkoutTestDataDefault);\n await fillPaymentInformation(page, checkoutTestDataDefault);\n });\n\n await test.step('Submit the reservation', async () => {\n await submitBookingReservation(page);\n });\n\n await test.step('Verify booking confirmation', async () => {\n await verifyBookingConfirmation(page, checkoutTestDataDefault);\n });\n\n // Now that we've checked out, we want to test that we can navigate back to a previous step\n await test.step('Go back to Choose Accommodation step.', async () => {\n // Clicking any step after 'Choose Accommodation' should take us back to 'Choose Accommodation'.\n // Let's click on the Confirmation step.\n const confirmationStepLink = page.locator('.step-selector__item p.text-body:has-text(\"Confirmation\")');\n await expect(confirmationStepLink).toBeVisible();\n await confirmationStepLink.click({ force: true }); // Force because of the <a> element which intercepts the click.\n\n // We should now be on the 'Choose Accommodation step'.\n const currentStep = page.locator('.step-selector__item.is-current');\n await expect(currentStep).toContainText('Choose Accommodation');\n });\n\n await test.step('Try to click back to the Thanks step (this should be prevented).', async () => {\n const thanksStepContainer = page.locator('.step-selector__item:has(p.text-body:has-text(\"Thanks\"))');\n const thanksStepAnchor = thanksStepContainer.locator('a');\n\n // The step container should have the 'not-allowed' cursor.\n const cursorStyle = await thanksStepContainer.evaluate((element) => {\n return window.getComputedStyle(element).cursor;\n });\n expect(cursorStyle).toBe('not-allowed');\n\n // This link shouldn't be clickable.\n await expect(thanksStepAnchor).not.toBeVisible();\n });\n\n await test.step('Check out again, using the same dates but with different contact information.', async () => {\n await proceedToConfirmationStep(page);\n await fillContactInfo(page, checkoutTestDataSecondary);\n await fillPaymentInformation(page, checkoutTestDataSecondary);\n await submitBookingReservation(page);\n await verifyBookingConfirmation(page, checkoutTestDataSecondary);\n });\n});"]}
|
|
1
|
+
{"version":3,"file":"goBackAndCheckoutAgain.spec.js","sourceRoot":"/","sources":["e2e/goBackAndCheckoutAgain.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect } from '@playwright/test';\nimport { fillContactInfo, fillPaymentInformation, proceedToConfirmationStep, selectAvailableDates, submitBookingReservation, verifyBookingConfirmation } from './helpers/checkoutHelpers';\nimport { checkoutTestDataDefault, checkoutTestDataSecondary } from './data/checkoutTestData';\n\n// This test just runs on the Frontend Demo, as it needs to actually be able to check out with fake payment details.\nconst url = 'http://localhost:9000/';\n\ntest(`can checkout on ${url}, and then go back and checkout again.`, async ({ page }) => {\n // This test can take a while to complete if we need to check various different date ranges to find\n // an available check-in and check-out date, so we need to increase the timeout.\n test.setTimeout(60000); // 1 minute.\n await page.goto(url);\n\n await test.step('Select available dates', async () => {\n const foundAvailableDates = await selectAvailableDates(page);\n if (!foundAvailableDates) {\n console.error('Unable to find available dates after maximum retries.');\n test.fail();\n return;\n }\n });\n\n await test.step('Proceed to confirmation step', async () => {\n await proceedToConfirmationStep(page);\n });\n\n await test.step('Fill contact and payment information', async () => {\n await fillContactInfo(page, checkoutTestDataDefault);\n await fillPaymentInformation(page, checkoutTestDataDefault);\n });\n\n await test.step('Submit the reservation', async () => {\n await submitBookingReservation(page);\n });\n\n await test.step('Verify booking confirmation', async () => {\n await verifyBookingConfirmation(page, checkoutTestDataDefault);\n });\n\n // Now that we've checked out, we want to test that we can navigate back to a previous step\n await test.step('Go back to Choose Accommodation step.', async () => {\n // Clicking any step after 'Choose Accommodation' should take us back to 'Choose Accommodation'.\n // Let's click on the Confirmation step.\n const confirmationStepLink = page.locator('.step-selector__item p.text-body:has-text(\"Confirmation\")');\n await expect(confirmationStepLink).toBeVisible();\n await confirmationStepLink.click({ force: true }); // Force because of the <a> element which intercepts the click.\n\n // We should now be on the 'Choose Accommodation step'.\n const currentStep = page.locator('.step-selector__item.is-current');\n await expect(currentStep).toContainText('Choose Accommodation');\n });\n\n await test.step('Try to click back to the Thanks step (this should be prevented).', async () => {\n const thanksStepContainer = page.locator('.step-selector__item:has(p.text-body:has-text(\"Thanks\"))');\n const thanksStepAnchor = thanksStepContainer.locator('a');\n\n // The step container should have the 'not-allowed' cursor.\n const cursorStyle = await thanksStepContainer.evaluate((element) => {\n return window.getComputedStyle(element).cursor;\n });\n expect(cursorStyle).toBe('not-allowed');\n\n // This link shouldn't be clickable.\n await expect(thanksStepAnchor).not.toBeVisible();\n });\n\n await test.step('Check out again, using the same dates but with different contact information.', async () => {\n await proceedToConfirmationStep(page);\n await fillContactInfo(page, checkoutTestDataSecondary);\n await fillPaymentInformation(page, checkoutTestDataSecondary);\n await submitBookingReservation(page);\n await verifyBookingConfirmation(page, checkoutTestDataSecondary);\n });\n});"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runPlaywrightTestWithConfig = void 0;
|
|
4
|
+
const frontendTestConfigs_1 = require("../frontendTestConfigs");
|
|
5
|
+
function runPlaywrightTestWithConfig(runTest) {
|
|
6
|
+
const specificUrl = process.env.URL;
|
|
7
|
+
const isClientsArg = process.env.CLIENTS;
|
|
8
|
+
let selectedConfigs;
|
|
9
|
+
if (specificUrl) {
|
|
10
|
+
// Find the matching config or create one for the given URL
|
|
11
|
+
const testConfig = frontendTestConfigs_1.testConfigs.find((config) => config.url === specificUrl) || {
|
|
12
|
+
url: specificUrl,
|
|
13
|
+
proceedWithPayment: false,
|
|
14
|
+
};
|
|
15
|
+
selectedConfigs = [testConfig];
|
|
16
|
+
}
|
|
17
|
+
else if (isClientsArg) {
|
|
18
|
+
selectedConfigs = frontendTestConfigs_1.testConfigs.filter((config) => config.isClient);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
// No URL provided, use the default config(s)
|
|
22
|
+
selectedConfigs = frontendTestConfigs_1.testConfigs.filter((config) => config.runByDefault);
|
|
23
|
+
}
|
|
24
|
+
selectedConfigs.forEach((config) => runTest(config));
|
|
25
|
+
}
|
|
26
|
+
exports.runPlaywrightTestWithConfig = runPlaywrightTestWithConfig;
|
|
27
|
+
//# sourceMappingURL=playwrightHelpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"playwrightHelpers.js","sourceRoot":"/","sources":["e2e/helpers/playwrightHelpers.ts"],"names":[],"mappings":";;;AAAA,gEAAyE;AAEzE,SAAgB,2BAA2B,CACzC,OAA6C;IAE7C,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;IACpC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC;IAEzC,IAAI,eAAqC,CAAC;IAE1C,IAAI,WAAW,EAAE;QACf,2DAA2D;QAC3D,MAAM,UAAU,GAAG,iCAAW,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,KAAK,WAAW,CAAC,IAAI;YAC7E,GAAG,EAAE,WAAW;YAChB,kBAAkB,EAAE,KAAK;SAC1B,CAAC;QAEF,eAAe,GAAG,CAAC,UAAU,CAAC,CAAC;KAChC;SAAM,IAAI,YAAY,EAAE;QACvB,eAAe,GAAG,iCAAW,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;KACnE;SAAM;QACL,6CAA6C;QAC7C,eAAe,GAAG,iCAAW,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;KACvE;IAED,eAAe,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AACvD,CAAC;AAxBD,kEAwBC","sourcesContent":["import { FrontendTestConfig, testConfigs } from \"../frontendTestConfigs\";\n\nexport function runPlaywrightTestWithConfig(\n runTest: (config: FrontendTestConfig) => void\n): void {\n const specificUrl = process.env.URL;\n const isClientsArg = process.env.CLIENTS;\n\n let selectedConfigs: FrontendTestConfig[];\n\n if (specificUrl) {\n // Find the matching config or create one for the given URL\n const testConfig = testConfigs.find((config) => config.url === specificUrl) || {\n url: specificUrl,\n proceedWithPayment: false,\n };\n\n selectedConfigs = [testConfig];\n } else if (isClientsArg) {\n selectedConfigs = testConfigs.filter((config) => config.isClient);\n } else {\n // No URL provided, use the default config(s)\n selectedConfigs = testConfigs.filter((config) => config.runByDefault);\n }\n\n selectedConfigs.forEach((config) => runTest(config));\n}"]}
|