@camphoric/camphoric-event-import-tools 2.1.0 → 2.2.0
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/CHANGELOG.md +12 -0
- package/README.md +53 -4
- package/dist/e2e.d.ts +17 -3
- package/dist/e2e.d.ts.map +1 -1
- package/dist/e2e.js +60 -7
- package/dist/e2e.js.map +1 -1
- package/dist/e2eAdmin.d.ts +59 -0
- package/dist/e2eAdmin.d.ts.map +1 -0
- package/dist/e2eAdmin.js +103 -0
- package/dist/e2eAdmin.js.map +1 -0
- package/dist/e2eImport.d.ts +1 -0
- package/dist/e2eImport.d.ts.map +1 -1
- package/dist/e2eImport.js +8 -4
- package/dist/e2eImport.js.map +1 -1
- package/dist/e2ePayPal.d.ts +34 -0
- package/dist/e2ePayPal.d.ts.map +1 -0
- package/dist/e2ePayPal.js +104 -0
- package/dist/e2ePayPal.js.map +1 -0
- package/dist/e2eRegistrationForm.d.ts +42 -0
- package/dist/e2eRegistrationForm.d.ts.map +1 -1
- package/dist/e2eRegistrationForm.js +99 -0
- package/dist/e2eRegistrationForm.js.map +1 -1
- package/dist/e2eServer.d.ts +2 -0
- package/dist/e2eServer.d.ts.map +1 -1
- package/dist/e2eServer.js +14 -1
- package/dist/e2eServer.js.map +1 -1
- package/e2e-compose.yml +38 -3
- package/e2e.ts +67 -9
- package/e2eAdmin.ts +174 -0
- package/e2eFakePayPal.py +112 -0
- package/e2eImport.ts +13 -2
- package/e2ePayPal.ts +129 -0
- package/e2eRegistrationForm.ts +108 -0
- package/e2eServer.ts +19 -1
- package/package.json +4 -1
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PayPal, faked for an event's e2e tests. The throwaway server's PayPal API is
|
|
3
|
+
* e2eFakePayPal.py, and the browser's PayPal script is FAKE_PAYPAL_SDK (the
|
|
4
|
+
* `test` fixture serves it in place of PayPal's), so the payment step's
|
|
5
|
+
* PayPal buttons work without a PayPal account and nothing is paid.
|
|
6
|
+
*/
|
|
7
|
+
// The client id an event is imported with for online payment (e2eImport.ts):
|
|
8
|
+
// only the fakes accept it
|
|
9
|
+
export const E2E_PAYPAL_CLIENT_ID = 'camphoric-e2e-fake-paypal';
|
|
10
|
+
// PayPal's script, wherever the client loads it from
|
|
11
|
+
export const PAYPAL_SDK_URL = /^https:\/\/www\.(sandbox\.)?paypal\.com\/sdk\/js(\?|$)/;
|
|
12
|
+
/** The fake PayPal API's record of the orders the server created. */
|
|
13
|
+
export class FakePayPal {
|
|
14
|
+
url;
|
|
15
|
+
constructor(url) {
|
|
16
|
+
this.url = url.replace(/\/$/, '');
|
|
17
|
+
}
|
|
18
|
+
/** Every order the server created, oldest first. */
|
|
19
|
+
async orders() {
|
|
20
|
+
const recorded = await this.get('/e2e/orders');
|
|
21
|
+
return recorded.map(order);
|
|
22
|
+
}
|
|
23
|
+
/** The order with this id, as the server asked for it. */
|
|
24
|
+
async order(id) {
|
|
25
|
+
return order(await this.get(`/e2e/orders/${encodeURIComponent(id)}`));
|
|
26
|
+
}
|
|
27
|
+
async get(path) {
|
|
28
|
+
const response = await fetch(`${this.url}${path}`);
|
|
29
|
+
if (!response.ok) {
|
|
30
|
+
throw new Error(`the fake PayPal answered ${response.status} to ${path}: ${await response.text()}`);
|
|
31
|
+
}
|
|
32
|
+
return response.json();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function order(recorded) {
|
|
36
|
+
const amount = recorded.body.purchase_units?.[0]?.amount;
|
|
37
|
+
return {
|
|
38
|
+
id: recorded.id,
|
|
39
|
+
amount: amount?.value ?? '',
|
|
40
|
+
currency: amount?.currency_code ?? '',
|
|
41
|
+
body: recorded.body,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* PayPal's browser script, faked: `paypal.Buttons()` draws a "PayPal" and a
|
|
46
|
+
* "Debit or Credit Card" button, as the client's PayPal library expects. A
|
|
47
|
+
* click does what PayPal's does up to its popup: onClick, then createOrder
|
|
48
|
+
* (which asks the server for the order). The popup then stays "open": the
|
|
49
|
+
* payer never approves or cancels, so nothing is captured.
|
|
50
|
+
*/
|
|
51
|
+
export const FAKE_PAYPAL_SDK = `(() => {
|
|
52
|
+
const buttons = [['paypal', 'PayPal'], ['card', 'Debit or Credit Card']];
|
|
53
|
+
window.paypal = {
|
|
54
|
+
version: 'camphoric-e2e-fake',
|
|
55
|
+
FUNDING: { PAYPAL: 'paypal', CARD: 'card' },
|
|
56
|
+
Buttons(props) {
|
|
57
|
+
let container = null;
|
|
58
|
+
const elements = [];
|
|
59
|
+
// Disabled (as the client does while it's busy) by the buttons' own
|
|
60
|
+
// attribute, so a test's click waits until they're enabled
|
|
61
|
+
const setDisabled = (disabled) => {
|
|
62
|
+
for (const button of elements) button.disabled = disabled;
|
|
63
|
+
return Promise.resolve();
|
|
64
|
+
};
|
|
65
|
+
const actions = { enable: () => setDisabled(false), disable: () => setDisabled(true) };
|
|
66
|
+
const pay = async (fundingSource) => {
|
|
67
|
+
const data = { fundingSource };
|
|
68
|
+
const clickActions = { resolve: () => Promise.resolve(), reject: () => Promise.resolve() };
|
|
69
|
+
if (props.onClick && (await props.onClick(data, clickActions)) === false) return;
|
|
70
|
+
try {
|
|
71
|
+
await props.createOrder(data, {});
|
|
72
|
+
} catch (error) {
|
|
73
|
+
if (props.onError) props.onError(error);
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
return {
|
|
77
|
+
isEligible: () => true,
|
|
78
|
+
render(target) {
|
|
79
|
+
container = typeof target === 'string' ? document.querySelector(target) : target;
|
|
80
|
+
const box = document.createElement('div');
|
|
81
|
+
box.setAttribute('data-camphoric-e2e-paypal', '');
|
|
82
|
+
for (const [fundingSource, label] of buttons) {
|
|
83
|
+
const button = document.createElement('button');
|
|
84
|
+
button.type = 'button';
|
|
85
|
+
button.textContent = label;
|
|
86
|
+
button.addEventListener('click', () => { pay(fundingSource); });
|
|
87
|
+
elements.push(button);
|
|
88
|
+
box.appendChild(button);
|
|
89
|
+
}
|
|
90
|
+
container.appendChild(box);
|
|
91
|
+
if (props.onInit) props.onInit({}, actions);
|
|
92
|
+
return Promise.resolve();
|
|
93
|
+
},
|
|
94
|
+
updateProps: () => Promise.resolve(),
|
|
95
|
+
close() {
|
|
96
|
+
if (container) container.replaceChildren();
|
|
97
|
+
return Promise.resolve();
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
})();
|
|
103
|
+
`;
|
|
104
|
+
//# sourceMappingURL=e2ePayPal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"e2ePayPal.js","sourceRoot":"","sources":["../e2ePayPal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAmBH,6EAA6E;AAC7E,2BAA2B;AAC3B,MAAM,CAAC,MAAM,oBAAoB,GAAG,2BAA2B,CAAC;AAEhE,qDAAqD;AACrD,MAAM,CAAC,MAAM,cAAc,GAAG,wDAAwD,CAAC;AAEvF,qEAAqE;AACrE,MAAM,OAAO,UAAU;IACZ,GAAG,CAAS;IAErB,YAAY,GAAW;QACrB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC;IAED,oDAAoD;IACpD,KAAK,CAAC,MAAM;QACV,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,aAAa,CAAoB,CAAC;QAClE,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAED,0DAA0D;IAC1D,KAAK,CAAC,KAAK,CAAC,EAAU;QACpB,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,eAAe,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAkB,CAAC,CAAC;IACzF,CAAC;IAEO,KAAK,CAAC,GAAG,CAAC,IAAY;QAC5B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,GAAG,IAAI,EAAE,CAAC,CAAC;QACnD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,QAAQ,CAAC,MAAM,OAAO,IAAI,KAAK,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;IACzB,CAAC;CACF;AAED,SAAS,KAAK,CAAC,QAAuB;IACpC,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;IACzD,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE;QACf,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,EAAE;QAC3B,QAAQ,EAAE,MAAM,EAAE,aAAa,IAAI,EAAE;QACrC,IAAI,EAAE,QAAQ,CAAC,IAA+B;KAC/C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAoD9B,CAAC"}
|
|
@@ -22,6 +22,27 @@ export declare class FormSection {
|
|
|
22
22
|
check(label: string | RegExp): Promise<void>;
|
|
23
23
|
/** A message shown with the questions, such as a validation error. */
|
|
24
24
|
message(text: string | RegExp): Locator;
|
|
25
|
+
/**
|
|
26
|
+
* A list question (an array of objects in the event's schema, such as a
|
|
27
|
+
* camper's parking passes), by its title: its items, and adding and
|
|
28
|
+
* removing them. A camper's list is the camper's: `camper(n).list(title)`
|
|
29
|
+
* (on the whole form, every camper's list has that title).
|
|
30
|
+
*/
|
|
31
|
+
list(title: string): ListQuestion;
|
|
32
|
+
}
|
|
33
|
+
/** A list question's items, each with questions of its own (FormSection.list). */
|
|
34
|
+
export declare class ListQuestion {
|
|
35
|
+
readonly page: Page;
|
|
36
|
+
readonly root: Locator;
|
|
37
|
+
constructor(page: Page, root: Locator);
|
|
38
|
+
/** Its items, in order: count them with `expect(list.items()).toHaveCount(n)`. */
|
|
39
|
+
items(): Locator;
|
|
40
|
+
/** The nth item's questions (from 1). */
|
|
41
|
+
item(n: number): FormSection;
|
|
42
|
+
/** Adds an item (its "Add …" button), returning its questions. */
|
|
43
|
+
add(): Promise<FormSection>;
|
|
44
|
+
/** Removes the nth item (from 1), with its × button. */
|
|
45
|
+
remove(n: number): Promise<void>;
|
|
25
46
|
}
|
|
26
47
|
/** One camper's questions, under its "1st Camper", "2nd Camper", … heading. */
|
|
27
48
|
export declare class CamperSection extends FormSection {
|
|
@@ -55,6 +76,11 @@ export declare class RegistrationForm extends FormSection {
|
|
|
55
76
|
camper(n: number): CamperSection;
|
|
56
77
|
/** Adds another camper, returning its questions. */
|
|
57
78
|
addCamper(): Promise<CamperSection>;
|
|
79
|
+
/**
|
|
80
|
+
* Removes the nth camper (from 1), with the Remove button by its heading;
|
|
81
|
+
* the campers after it move up (the 3rd becomes the 2nd).
|
|
82
|
+
*/
|
|
83
|
+
removeCamper(n: number): Promise<void>;
|
|
58
84
|
/** Waits until the price ticker shows this total (in dollars). */
|
|
59
85
|
expectTotal(amount: number): Promise<void>;
|
|
60
86
|
/** The total the price ticker shows now, in dollars (see expectTotal). */
|
|
@@ -67,5 +93,21 @@ export declare class RegistrationForm extends FormSection {
|
|
|
67
93
|
choosePaymentOption(title: string): Promise<void>;
|
|
68
94
|
/** On the payment step: pays by check, completing the registration. */
|
|
69
95
|
payByCheck(): Promise<void>;
|
|
96
|
+
/**
|
|
97
|
+
* On the payment step: what the chosen payment option costs, in dollars,
|
|
98
|
+
* as it shows it: by check (the default), or online, which adds the
|
|
99
|
+
* event's e-payment handling (shown only when the event takes payments
|
|
100
|
+
* online: import it with `onlinePayment`).
|
|
101
|
+
*/
|
|
102
|
+
paymentTotal(how?: 'check' | 'online'): Promise<number>;
|
|
103
|
+
/**
|
|
104
|
+
* On the payment step of an event imported with `onlinePayment`: presses
|
|
105
|
+
* a PayPal button ('PayPal', or 'Card' for "Debit or Credit Card"), which
|
|
106
|
+
* completes the registration and has the server create its PayPal order,
|
|
107
|
+
* and returns the order's id. The fake PayPal's window then stays open: the
|
|
108
|
+
* payer never approves, so nothing is paid. Read what the order asked for
|
|
109
|
+
* with the `payPal` fixture's `order(id)`.
|
|
110
|
+
*/
|
|
111
|
+
startOnlinePayment(button?: 'PayPal' | 'Card'): Promise<string>;
|
|
70
112
|
}
|
|
71
113
|
//# sourceMappingURL=e2eRegistrationForm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2eRegistrationForm.d.ts","sourceRoot":"","sources":["../e2eRegistrationForm.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAU,KAAK,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AA0CnE,6EAA6E;AAC7E,qBAAa,WAAW;IACtB,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAEX,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO;IAKrC;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO;IAItC,gEAAgE;IAC1D,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhE,sEAAsE;IAChE,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAInE,2EAA2E;IACrE,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlD,sEAAsE;IACtE,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO;
|
|
1
|
+
{"version":3,"file":"e2eRegistrationForm.d.ts","sourceRoot":"","sources":["../e2eRegistrationForm.ts"],"names":[],"mappings":"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"}
|
|
@@ -73,6 +73,49 @@ export class FormSection {
|
|
|
73
73
|
message(text) {
|
|
74
74
|
return this.root.getByText(text);
|
|
75
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* A list question (an array of objects in the event's schema, such as a
|
|
78
|
+
* camper's parking passes), by its title: its items, and adding and
|
|
79
|
+
* removing them. A camper's list is the camper's: `camper(n).list(title)`
|
|
80
|
+
* (on the whole form, every camper's list has that title).
|
|
81
|
+
*/
|
|
82
|
+
list(title) {
|
|
83
|
+
// The list's own title (its heading, a child of the list's box), not
|
|
84
|
+
// that of a list inside one of its items
|
|
85
|
+
const heading = this.page.locator(':scope > h3').filter({ hasText: new RegExp(`^${escapeRegExp(title)}$`) });
|
|
86
|
+
return new ListQuestion(this.page, this.root.locator('.rjsf-field-array').filter({ has: heading }));
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/** A list question's items, each with questions of its own (FormSection.list). */
|
|
90
|
+
export class ListQuestion {
|
|
91
|
+
page;
|
|
92
|
+
root;
|
|
93
|
+
constructor(page, root) {
|
|
94
|
+
this.page = page;
|
|
95
|
+
this.root = root;
|
|
96
|
+
}
|
|
97
|
+
/** Its items, in order: count them with `expect(list.items()).toHaveCount(n)`. */
|
|
98
|
+
items() {
|
|
99
|
+
return this.root.locator(':scope > .rjsf-array-item-list > .rjsf-array-item');
|
|
100
|
+
}
|
|
101
|
+
/** The nth item's questions (from 1). */
|
|
102
|
+
item(n) {
|
|
103
|
+
return new FormSection(this.page, this.items().nth(n - 1));
|
|
104
|
+
}
|
|
105
|
+
/** Adds an item (its "Add …" button), returning its questions. */
|
|
106
|
+
async add() {
|
|
107
|
+
const count = await this.items().count();
|
|
108
|
+
await this.root.locator(':scope > * > .rjsf-array-item-add').click();
|
|
109
|
+
await expect(this.items()).toHaveCount(count + 1);
|
|
110
|
+
return this.item(count + 1);
|
|
111
|
+
}
|
|
112
|
+
/** Removes the nth item (from 1), with its × button. */
|
|
113
|
+
async remove(n) {
|
|
114
|
+
const count = await this.items().count();
|
|
115
|
+
await this.items().nth(n - 1).locator(':scope > .rjsf-array-item-toolbar')
|
|
116
|
+
.getByRole('button', { name: 'Remove', exact: true }).click();
|
|
117
|
+
await expect(this.items()).toHaveCount(count - 1);
|
|
118
|
+
}
|
|
76
119
|
}
|
|
77
120
|
/** One camper's questions, under its "1st Camper", "2nd Camper", … heading. */
|
|
78
121
|
export class CamperSection extends FormSection {
|
|
@@ -135,6 +178,17 @@ export class RegistrationForm extends FormSection {
|
|
|
135
178
|
await this.page.getByRole('button', { name: `Add a ${ordinal(count + 1)} Camper` }).click();
|
|
136
179
|
return this.camper(count + 1);
|
|
137
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Removes the nth camper (from 1), with the Remove button by its heading;
|
|
183
|
+
* the campers after it move up (the 3rd becomes the 2nd).
|
|
184
|
+
*/
|
|
185
|
+
async removeCamper(n) {
|
|
186
|
+
const count = await this.page.locator('.camphoric-camper').count();
|
|
187
|
+
// (The heading's row, not the Remove buttons of the camper's lists)
|
|
188
|
+
await this.camper(n).root.locator(':scope > .mantine-Group-root')
|
|
189
|
+
.getByRole('button', { name: 'Remove', exact: true }).click();
|
|
190
|
+
await expect(this.page.locator('.camphoric-camper')).toHaveCount(count - 1);
|
|
191
|
+
}
|
|
138
192
|
/** Waits until the price ticker shows this total (in dollars). */
|
|
139
193
|
async expectTotal(amount) {
|
|
140
194
|
await expect(this.page.getByText(/^Total: /)).toHaveText(`Total: ${money(amount)}`);
|
|
@@ -163,5 +217,50 @@ export class RegistrationForm extends FormSection {
|
|
|
163
217
|
async payByCheck() {
|
|
164
218
|
await this.page.getByRole('button', { name: /by check$/ }).click();
|
|
165
219
|
}
|
|
220
|
+
/**
|
|
221
|
+
* On the payment step: what the chosen payment option costs, in dollars,
|
|
222
|
+
* as it shows it: by check (the default), or online, which adds the
|
|
223
|
+
* event's e-payment handling (shown only when the event takes payments
|
|
224
|
+
* online: import it with `onlinePayment`).
|
|
225
|
+
*/
|
|
226
|
+
async paymentTotal(how = 'check') {
|
|
227
|
+
const due = this.page.getByRole('table', { name: 'Amount due now' });
|
|
228
|
+
const row = due.getByRole('row').filter({ hasText: how === 'check' ? /^By check/ : /^Online/ });
|
|
229
|
+
const amount = row.getByRole('cell').last();
|
|
230
|
+
await expect(amount).toBeVisible();
|
|
231
|
+
return Number(((await amount.textContent()) ?? '').replace(/[^0-9.-]/g, ''));
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* On the payment step of an event imported with `onlinePayment`: presses
|
|
235
|
+
* a PayPal button ('PayPal', or 'Card' for "Debit or Credit Card"), which
|
|
236
|
+
* completes the registration and has the server create its PayPal order,
|
|
237
|
+
* and returns the order's id. The fake PayPal's window then stays open: the
|
|
238
|
+
* payer never approves, so nothing is paid. Read what the order asked for
|
|
239
|
+
* with the `payPal` fixture's `order(id)`.
|
|
240
|
+
*/
|
|
241
|
+
async startOnlinePayment(button = 'PayPal') {
|
|
242
|
+
const name = button === 'Card' ? 'Debit or Credit Card' : 'PayPal';
|
|
243
|
+
const created = this.page.waitForResponse((response) => {
|
|
244
|
+
const request = response.request();
|
|
245
|
+
// (With an invitation, the form posts with its code in the query)
|
|
246
|
+
if (request.method() !== 'POST' || new URL(response.url()).pathname !== `/api/events/${this.eventId}/register`) {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
return request.postDataJSON()?.step === 'paypal-order';
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
await this.page.locator('[data-camphoric-e2e-paypal]')
|
|
257
|
+
.getByRole('button', { name, exact: true }).click();
|
|
258
|
+
const response = await created;
|
|
259
|
+
const body = await response.json();
|
|
260
|
+
if (!response.ok() || !body.orderID) {
|
|
261
|
+
throw new Error(`the server didn't create a PayPal order (${response.status()}): ${body.detail ?? JSON.stringify(body)}`);
|
|
262
|
+
}
|
|
263
|
+
return body.orderID;
|
|
264
|
+
}
|
|
166
265
|
}
|
|
167
266
|
//# sourceMappingURL=e2eRegistrationForm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2eRegistrationForm.js","sourceRoot":"","sources":["../e2eRegistrationForm.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"e2eRegistrationForm.js","sourceRoot":"","sources":["../e2eRegistrationForm.ts"],"names":[],"mappings":"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"}
|
package/dist/e2eServer.d.ts
CHANGED
|
@@ -6,10 +6,12 @@ export interface CamphoricServer {
|
|
|
6
6
|
url: string;
|
|
7
7
|
username: string;
|
|
8
8
|
password: string;
|
|
9
|
+
payPalUrl?: string;
|
|
9
10
|
stop: () => Promise<void>;
|
|
10
11
|
}
|
|
11
12
|
export interface CamphoricServerOptions {
|
|
12
13
|
image?: string;
|
|
14
|
+
fakePayPal?: boolean;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Start a throwaway Camphoric, ready for requests. To use an existing server
|
package/dist/e2eServer.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2eServer.d.ts","sourceRoot":"","sources":["../e2eServer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IAEZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"e2eServer.d.ts","sourceRoot":"","sources":["../e2eServer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAYH,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IAEZ,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IAGjB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB;IAIrC,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAwBD;;;;;;GAMG;AACH,wBAAsB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,eAAe,CAAC,CAiEpG"}
|
package/dist/e2eServer.js
CHANGED
|
@@ -48,6 +48,10 @@ export async function camphoricServer(options = {}) {
|
|
|
48
48
|
return { url: existing.replace(/\/$/, ''), username, password, stop: async () => { } };
|
|
49
49
|
}
|
|
50
50
|
const port = await freePort();
|
|
51
|
+
let payPalPort = await freePort();
|
|
52
|
+
while (payPalPort === port)
|
|
53
|
+
payPalPort = await freePort();
|
|
54
|
+
const fakePayPal = options.fakePayPal ?? false;
|
|
51
55
|
const username = 'e2e-admin';
|
|
52
56
|
const password = randomBytes(12).toString('hex');
|
|
53
57
|
const project = `camphoric-e2e-${randomBytes(4).toString('hex')}`;
|
|
@@ -57,6 +61,9 @@ export async function camphoricServer(options = {}) {
|
|
|
57
61
|
CAMPHORIC_E2E_IMAGE: local ?? `ghcr.io/camphoric/camphoric:${process.env.CAMPHORIC_IMAGE_TAG ?? 'latest'}`,
|
|
58
62
|
CAMPHORIC_E2E_PULL_POLICY: local ? 'missing' : 'always',
|
|
59
63
|
CAMPHORIC_E2E_PORT: String(port),
|
|
64
|
+
CAMPHORIC_E2E_PAYPAL_PORT: String(payPalPort),
|
|
65
|
+
// (for every compose command, so `down` removes the fake PayPal too)
|
|
66
|
+
COMPOSE_PROFILES: fakePayPal ? 'paypal' : '',
|
|
60
67
|
CAMPHORIC_E2E_USERNAME: username,
|
|
61
68
|
CAMPHORIC_E2E_PASSWORD: password,
|
|
62
69
|
};
|
|
@@ -88,6 +95,12 @@ export async function camphoricServer(options = {}) {
|
|
|
88
95
|
process.off('SIGINT', interrupted);
|
|
89
96
|
process.off('SIGTERM', interrupted);
|
|
90
97
|
}
|
|
91
|
-
return {
|
|
98
|
+
return {
|
|
99
|
+
url: `http://localhost:${port}`,
|
|
100
|
+
username,
|
|
101
|
+
password,
|
|
102
|
+
payPalUrl: fakePayPal ? `http://127.0.0.1:${payPalPort}` : undefined,
|
|
103
|
+
stop,
|
|
104
|
+
};
|
|
92
105
|
}
|
|
93
106
|
//# sourceMappingURL=e2eServer.js.map
|
package/dist/e2eServer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"e2eServer.js","sourceRoot":"","sources":["../e2eServer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,GAAG,MAAM,UAAU,CAAC;AAC3B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,GAAG,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"e2eServer.js","sourceRoot":"","sources":["../e2eServer.ts"],"names":[],"mappings":"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"}
|
package/e2e-compose.yml
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# A throwaway Camphoric for an event's e2e tests (camphoricServer() in
|
|
2
2
|
# e2eServer.ts): the release image and its Postgres, on a free port, with an
|
|
3
|
-
# admin to import as. It holds nothing worth
|
|
3
|
+
# admin to import as, and a stand-in for PayPal's API. It holds nothing worth
|
|
4
|
+
# keeping: `down -v` removes it.
|
|
4
5
|
services:
|
|
5
6
|
postgres:
|
|
6
7
|
image: postgres:16-alpine
|
|
@@ -23,10 +24,20 @@ services:
|
|
|
23
24
|
SECRET_KEY: e2e-only-not-a-secret
|
|
24
25
|
DATABASE_URL: postgres://camphoric:camphoric@postgres/camphoric
|
|
25
26
|
DEBUG: "off"
|
|
26
|
-
|
|
27
|
+
# PayPal's API is the fake below, which records the orders it's asked
|
|
28
|
+
# for (started only for online payment: without it, no order is made)
|
|
29
|
+
PAYPAL_BASE_URL: http://paypal:8000
|
|
27
30
|
PAYPAL_SECRET: unused
|
|
28
|
-
#
|
|
31
|
+
# Email is delivered as it's queued (no worker), to the console: the
|
|
32
|
+
# outbox (/api/emailmessages/) keeps what was sent, for the tests to read
|
|
33
|
+
CAMPHORIC_EMAIL_QUEUE: immediate
|
|
29
34
|
CAMPHORIC_EMAIL_FORCE_BACKEND: django.core.mail.backends.console.EmailBackend
|
|
35
|
+
# A suite registers more a minute than a registrant would (from the
|
|
36
|
+
# throttles' one address): their limits would make tests fail at random
|
|
37
|
+
CAMPHORIC_REGISTER_RATE: ${CAMPHORIC_E2E_REGISTER_RATE:-1000/minute}
|
|
38
|
+
CAMPHORIC_REGISTRATION_DRAFT_RATE: ${CAMPHORIC_E2E_REGISTRATION_DRAFT_RATE:-1000/minute}
|
|
39
|
+
CAMPHORIC_INVITATION_LOOKUP_RATE: ${CAMPHORIC_E2E_INVITATION_LOOKUP_RATE:-1000/minute}
|
|
40
|
+
CAMPHORIC_PROMO_CODE_CHECK_RATE: ${CAMPHORIC_E2E_PROMO_CODE_CHECK_RATE:-1000/minute}
|
|
30
41
|
ALLOWED_HOSTS: localhost,127.0.0.1
|
|
31
42
|
CSRF_TRUSTED_ORIGINS: http://localhost:${CAMPHORIC_E2E_PORT},http://127.0.0.1:${CAMPHORIC_E2E_PORT}
|
|
32
43
|
SESSION_COOKIE_SECURE: "false"
|
|
@@ -38,3 +49,27 @@ services:
|
|
|
38
49
|
depends_on:
|
|
39
50
|
postgres:
|
|
40
51
|
condition: service_healthy
|
|
52
|
+
paypal:
|
|
53
|
+
condition: service_healthy
|
|
54
|
+
# (in the paypal profile only)
|
|
55
|
+
required: false
|
|
56
|
+
|
|
57
|
+
# PayPal's Orders API, faked (e2eFakePayPal.py): it creates orders, never
|
|
58
|
+
# captures them, and tells the tests what each order asked for. It runs on
|
|
59
|
+
# the app image's Python, so there's nothing more to pull, but needs Docker
|
|
60
|
+
# to see this package's files (the bind mount), so it's started only for an
|
|
61
|
+
# event imported with online payment (COMPOSE_PROFILES=paypal).
|
|
62
|
+
paypal:
|
|
63
|
+
profiles: [paypal]
|
|
64
|
+
image: ${CAMPHORIC_E2E_IMAGE:-ghcr.io/camphoric/camphoric:latest}
|
|
65
|
+
pull_policy: missing
|
|
66
|
+
entrypoint: ["python", "/e2e/fake_paypal.py"]
|
|
67
|
+
volumes:
|
|
68
|
+
- ./e2eFakePayPal.py:/e2e/fake_paypal.py:ro
|
|
69
|
+
healthcheck:
|
|
70
|
+
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=3)"]
|
|
71
|
+
interval: 1s
|
|
72
|
+
timeout: 5s
|
|
73
|
+
retries: 30
|
|
74
|
+
ports:
|
|
75
|
+
- "127.0.0.1:${CAMPHORIC_E2E_PAYPAL_PORT}:8000"
|
package/e2e.ts
CHANGED
|
@@ -20,11 +20,18 @@
|
|
|
20
20
|
* with its registration open, and removes the throwaway server when the tests
|
|
21
21
|
* end. Every test, on every device, shares that one event: a registration
|
|
22
22
|
* one test completes stays, taking up lodging capacity the others see.
|
|
23
|
+
*
|
|
24
|
+
* A throwaway server's PayPal is a fake (e2ePayPal.ts): with `onlinePayment`
|
|
25
|
+
* the payment step shows PayPal's buttons, and a test can read what the
|
|
26
|
+
* server asked PayPal for, without anything being paid.
|
|
23
27
|
*/
|
|
24
28
|
|
|
25
29
|
import { defineConfig, devices, test as base, type PlaywrightTestConfig } from '@playwright/test';
|
|
26
30
|
|
|
31
|
+
import { getAuthToken } from './getAuthInfo.ts';
|
|
32
|
+
import { CamphoricAdmin } from './e2eAdmin.ts';
|
|
27
33
|
import { importForE2E, type ImportForE2EOptions } from './e2eImport.ts';
|
|
34
|
+
import { FAKE_PAYPAL_SDK, FakePayPal, PAYPAL_SDK_URL } from './e2ePayPal.ts';
|
|
28
35
|
import { RegistrationForm } from './e2eRegistrationForm.ts';
|
|
29
36
|
import { camphoricServer, type CamphoricServerOptions } from './e2eServer.ts';
|
|
30
37
|
|
|
@@ -33,15 +40,23 @@ export { camphoricServer } from './e2eServer.ts';
|
|
|
33
40
|
export type { CamphoricServer, CamphoricServerOptions } from './e2eServer.ts';
|
|
34
41
|
export { importForE2E } from './e2eImport.ts';
|
|
35
42
|
export type { ImportForE2EOptions } from './e2eImport.ts';
|
|
36
|
-
export { CamperSection, FormSection, RegistrationForm } from './e2eRegistrationForm.ts';
|
|
43
|
+
export { CamperSection, FormSection, ListQuestion, RegistrationForm } from './e2eRegistrationForm.ts';
|
|
44
|
+
export { CamphoricAdmin } from './e2eAdmin.ts';
|
|
45
|
+
export type { E2EInvitation, EmailsOptions, InviteOptions, SentEmail } from './e2eAdmin.ts';
|
|
46
|
+
export { FakePayPal } from './e2ePayPal.ts';
|
|
47
|
+
export type { PayPalOrder } from './e2ePayPal.ts';
|
|
37
48
|
|
|
38
49
|
// What the global setup hands the tests (workers inherit its environment)
|
|
39
50
|
const URL_VARIABLE = 'CAMPHORIC_E2E_RUN_URL';
|
|
40
51
|
const EVENT_VARIABLE = 'CAMPHORIC_E2E_RUN_EVENT_ID';
|
|
52
|
+
// The admin's API token (signing in once: Camphoric throttles sign-in)
|
|
53
|
+
const TOKEN_VARIABLE = 'CAMPHORIC_E2E_RUN_TOKEN';
|
|
54
|
+
// A throwaway server's fake PayPal API
|
|
55
|
+
const PAYPAL_VARIABLE = 'CAMPHORIC_E2E_RUN_PAYPAL_URL';
|
|
41
56
|
|
|
42
57
|
export type SetUpEventOptions = Pick<ImportForE2EOptions,
|
|
43
|
-
'event' | 'validate' | 'withSampleRegistrations' | 'openRegistration'>
|
|
44
|
-
& CamphoricServerOptions
|
|
58
|
+
'event' | 'validate' | 'withSampleRegistrations' | 'openRegistration' | 'onlinePayment'>
|
|
59
|
+
& Omit<CamphoricServerOptions, 'fakePayPal'>;
|
|
45
60
|
|
|
46
61
|
/**
|
|
47
62
|
* A Playwright global setup: starts the server, imports the event, and
|
|
@@ -49,11 +64,18 @@ export type SetUpEventOptions = Pick<ImportForE2EOptions,
|
|
|
49
64
|
*/
|
|
50
65
|
export function setUpEvent(options: SetUpEventOptions): () => Promise<() => Promise<void>> {
|
|
51
66
|
return async () => {
|
|
52
|
-
const server = await camphoricServer(options);
|
|
67
|
+
const server = await camphoricServer({ ...options, fakePayPal: options.onlinePayment });
|
|
53
68
|
try {
|
|
69
|
+
if (options.onlinePayment && !server.payPalUrl) {
|
|
70
|
+
throw new Error('onlinePayment needs the throwaway server, whose PayPal is a fake: '
|
|
71
|
+
+ 'CAMPHORIC_E2E_SERVER_URL\'s PayPal would refuse its client id');
|
|
72
|
+
}
|
|
54
73
|
const eventId = await importForE2E({ ...options, ...server });
|
|
55
74
|
process.env[URL_VARIABLE] = server.url;
|
|
56
75
|
process.env[EVENT_VARIABLE] = String(eventId);
|
|
76
|
+
process.env[TOKEN_VARIABLE] = await getAuthToken(server.url);
|
|
77
|
+
if (server.payPalUrl) process.env[PAYPAL_VARIABLE] = server.payPalUrl;
|
|
78
|
+
else delete process.env[PAYPAL_VARIABLE];
|
|
57
79
|
} catch (e) {
|
|
58
80
|
await server.stop();
|
|
59
81
|
throw e;
|
|
@@ -88,18 +110,40 @@ export function defineEventE2EConfig(
|
|
|
88
110
|
});
|
|
89
111
|
}
|
|
90
112
|
|
|
113
|
+
// The server's URL, from the global setup
|
|
114
|
+
function serverUrl(): string {
|
|
115
|
+
const url = process.env[URL_VARIABLE];
|
|
116
|
+
if (!url) throw new Error('no Camphoric server: run these tests with a config from defineEventE2EConfig');
|
|
117
|
+
return url;
|
|
118
|
+
}
|
|
119
|
+
|
|
91
120
|
/**
|
|
92
121
|
* Playwright's test, with the server as its baseURL and these fixtures:
|
|
93
|
-
* `eventId`, the imported event's id
|
|
122
|
+
* `eventId`, the imported event's id; `registration`, its form; `admin`,
|
|
123
|
+
* what an organizer does (invitations, the email sent); and `payPal`, the
|
|
124
|
+
* throwaway server's fake PayPal (the orders the server created).
|
|
94
125
|
*/
|
|
95
126
|
// (Playwright reads a fixture's dependencies from its destructured first
|
|
96
127
|
// argument, so one with none takes an empty pattern.)
|
|
97
|
-
export const test = base.extend<{
|
|
128
|
+
export const test = base.extend<{
|
|
129
|
+
eventId: number,
|
|
130
|
+
registration: RegistrationForm,
|
|
131
|
+
admin: CamphoricAdmin,
|
|
132
|
+
payPal: FakePayPal,
|
|
133
|
+
}>({
|
|
98
134
|
// eslint-disable-next-line no-empty-pattern
|
|
99
135
|
baseURL: async ({}, use) => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
136
|
+
await use(serverUrl());
|
|
137
|
+
},
|
|
138
|
+
// With the fake PayPal API, the browser gets the fake PayPal script, whose
|
|
139
|
+
// buttons work with it
|
|
140
|
+
context: async ({ context }, use) => {
|
|
141
|
+
if (process.env[PAYPAL_VARIABLE]) {
|
|
142
|
+
await context.route(PAYPAL_SDK_URL, route => route.fulfill({
|
|
143
|
+
contentType: 'text/javascript', body: FAKE_PAYPAL_SDK,
|
|
144
|
+
}));
|
|
145
|
+
}
|
|
146
|
+
await use(context);
|
|
103
147
|
},
|
|
104
148
|
// eslint-disable-next-line no-empty-pattern
|
|
105
149
|
eventId: async ({}, use) => {
|
|
@@ -108,4 +152,18 @@ export const test = base.extend<{ eventId: number, registration: RegistrationFor
|
|
|
108
152
|
registration: async ({ page, eventId }, use) => {
|
|
109
153
|
await use(new RegistrationForm(page, eventId));
|
|
110
154
|
},
|
|
155
|
+
admin: async ({ eventId }, use) => {
|
|
156
|
+
const token = process.env[TOKEN_VARIABLE];
|
|
157
|
+
if (!token) throw new Error('no admin token: run these tests with a config from defineEventE2EConfig');
|
|
158
|
+
await use(new CamphoricAdmin(serverUrl(), token, eventId));
|
|
159
|
+
},
|
|
160
|
+
// eslint-disable-next-line no-empty-pattern
|
|
161
|
+
payPal: async ({}, use) => {
|
|
162
|
+
const url = process.env[PAYPAL_VARIABLE];
|
|
163
|
+
if (!url) {
|
|
164
|
+
throw new Error('no fake PayPal: it comes with the throwaway server (not CAMPHORIC_E2E_SERVER_URL) '
|
|
165
|
+
+ 'when setUpEvent is given onlinePayment: true');
|
|
166
|
+
}
|
|
167
|
+
await use(new FakePayPal(url));
|
|
168
|
+
},
|
|
111
169
|
});
|