@12-apps/payments-e2e 1.4.0 → 1.5.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/README.md +27 -5
- package/dist/steps/activation.steps.d.ts +2 -0
- package/dist/steps/activation.steps.d.ts.map +1 -0
- package/dist/steps/activation.steps.js +74 -0
- package/dist/steps/activation.steps.js.map +1 -0
- package/dist/steps/saved-card-wallet.steps.d.ts +2 -0
- package/dist/steps/saved-card-wallet.steps.d.ts.map +1 -0
- package/dist/steps/saved-card-wallet.steps.js +65 -0
- package/dist/steps/saved-card-wallet.steps.js.map +1 -0
- package/dist/world.d.ts +20 -0
- package/dist/world.d.ts.map +1 -1
- package/dist/world.js.map +1 -1
- package/features/activating-a-provider.feature +29 -0
- package/features/saving-a-card.feature +29 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,9 +4,10 @@ The buyer journeys for the payments checkout, as Gherkin you run **against your
|
|
|
4
4
|
own app**.
|
|
5
5
|
|
|
6
6
|
Mounting `createPaymentFlows` gives you a checkout. This gives you its
|
|
7
|
-
end-to-end coverage: twenty scenarios across
|
|
8
|
-
hand-off and return, provider failover, issuer
|
|
9
|
-
store that cannot charge at all,
|
|
7
|
+
end-to-end coverage: twenty-seven scenarios across ten features — PIX, card,
|
|
8
|
+
digital wallets, hosted hand-off and return, provider failover, issuer
|
|
9
|
+
declines, an unresolved charge, a store that cannot charge at all,
|
|
10
|
+
per-provider screens, and saving a card outside checkout. You implement one
|
|
10
11
|
port and add three lines of config. Nothing is copied, so a scenario added here
|
|
11
12
|
later runs in your app on the next version bump.
|
|
12
13
|
|
|
@@ -84,12 +85,33 @@ files do not change either way.
|
|
|
84
85
|
`pix-only` · `card` · `both-methods` · `hosted` · `awaiting` · `settles` ·
|
|
85
86
|
`declined` · `unresolved` · `unavailable` · `no-provider` ·
|
|
86
87
|
`no-provider-remedy` · `payments-off` · `two-mintable` · `redirect-head` ·
|
|
87
|
-
`google-pay` · `apple-pay` · `apple-pay-unsupported` · `
|
|
88
|
-
`screen-
|
|
88
|
+
`google-pay` · `apple-pay` · `apple-pay-unsupported` · `wallet` ·
|
|
89
|
+
`activation` · `screen-on-page` · `screen-handoff` · `screen-undeclared` ·
|
|
90
|
+
`screen-unknown`
|
|
89
91
|
|
|
90
92
|
Adding a member is a breaking change for hosts, deliberately: a scenario needing
|
|
91
93
|
a store nobody can build is a scenario that silently never runs.
|
|
92
94
|
|
|
95
|
+
`wallet` (added for FUT-183/FUT-478) is one of two members that are **not a
|
|
96
|
+
checkout**: `open(page, 'wallet')` must land the buyer on the package's
|
|
97
|
+
manage-cards surface (`screens.ManageCards` from `createPaymentFlows`) at a
|
|
98
|
+
store whose single provider can vault — the chain head declares the adapter
|
|
99
|
+
`vault` seam, the connection runs in stub mode, and the wallet starts empty.
|
|
100
|
+
The journey types the shared `DECLINE_PAN` for the refusal path, so no store
|
|
101
|
+
flag decides the outcome; the card does. Hosts upgrading across this version
|
|
102
|
+
must add the member to their `open` mapping or their world stops compiling —
|
|
103
|
+
which is the point.
|
|
104
|
+
|
|
105
|
+
`activation` (added for FUT-689) is the other, and the first **admin**-side
|
|
106
|
+
shape: `open(page, 'activation')` must land the OWNER on the settings panel of
|
|
107
|
+
one provider that declares `activationCharge`, connected in stub mode and
|
|
108
|
+
never charged — the sales switch starts locked off. The host's
|
|
109
|
+
`renderVerification` slot must render the shared card form plus the
|
|
110
|
+
`activation-*` test ids `src/steps/activation.steps.ts` documents (pay button,
|
|
111
|
+
outcome, refund line, and the raw enable-attempt probe pair). As in `wallet`,
|
|
112
|
+
the typed card decides the outcome: `DECLINE_PAN` is refused with a named
|
|
113
|
+
reason, anything else pays the cent and gets it refunded.
|
|
114
|
+
|
|
93
115
|
## Why this package ships compiled JavaScript
|
|
94
116
|
|
|
95
117
|
Its siblings export raw `.ts` through their `exports` map, because an
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation.steps.d.ts","sourceRoot":"","sources":["../../src/steps/activation.steps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { expect } from '@playwright/test';
|
|
2
|
+
import { DECLINE_PAN, fillCard, fillCpf } from '../helpers/checkout.js';
|
|
3
|
+
import { paymentsWorld } from '../world.js';
|
|
4
|
+
import { Given, Then, When } from './fixtures.js';
|
|
5
|
+
/**
|
|
6
|
+
* ACTIVATING A PROVIDER (FUT-463, made real for every SDK provider by
|
|
7
|
+
* FUT-689) — the merchant admin's side of the till.
|
|
8
|
+
*
|
|
9
|
+
* The package renders the switch and its lock (`payments-enabled-toggle`,
|
|
10
|
+
* `payments-enable-hint`, `payments-status`); the activation step itself is
|
|
11
|
+
* HOST-owned, rendered into the `renderVerification` slot. So these steps
|
|
12
|
+
* read two vocabularies:
|
|
13
|
+
*
|
|
14
|
+
* - the package's own test ids, which mean the same thing in any host;
|
|
15
|
+
* - the activation-step contract a host's slot must render — the shared
|
|
16
|
+
* card form (`card-number`…, `buyer-cpf`) plus `activation-pay`,
|
|
17
|
+
* `activation-result`, `activation-refunded`, `activation-error`, and the
|
|
18
|
+
* fixture probe pair `activation-enable-attempt` /
|
|
19
|
+
* `activation-enable-refusal` (a raw enable request and the refusal it
|
|
20
|
+
* gets, the same affordance the wire probe is).
|
|
21
|
+
*
|
|
22
|
+
* The card the owner types decides the outcome, exactly as in the wallet
|
|
23
|
+
* journey: the shared `DECLINE_PAN` is refused with a named reason, any other
|
|
24
|
+
* valid card pays the cent and gets it back.
|
|
25
|
+
*/
|
|
26
|
+
/** The "Recebendo vendas" switch — MUI puts the state on the inner checkbox. */
|
|
27
|
+
function salesSwitch(page) {
|
|
28
|
+
return page.getByTestId('payments-enabled-toggle').getByRole('checkbox');
|
|
29
|
+
}
|
|
30
|
+
Given('the owner opens the settings of a connected but unproven provider', async ({ page }) => {
|
|
31
|
+
await paymentsWorld().open(page, 'activation');
|
|
32
|
+
});
|
|
33
|
+
Then('the sales switch is locked off until a real charge lands', async ({ page }) => {
|
|
34
|
+
await expect(salesSwitch(page)).toBeDisabled();
|
|
35
|
+
// The package's own lock hint — the quoted words are its pt-BR product copy.
|
|
36
|
+
await expect(page.getByTestId('payments-enable-hint')).toContainText('depois dos 3 passos');
|
|
37
|
+
});
|
|
38
|
+
When('the owner tries to force the provider on anyway', async ({ page }) => {
|
|
39
|
+
await page.getByTestId('activation-enable-attempt').click();
|
|
40
|
+
});
|
|
41
|
+
Then('the enable request is refused as unproven', async ({ page }) => {
|
|
42
|
+
// The package's own refusal, by name: the server said no, not the screen.
|
|
43
|
+
await expect(page.getByTestId('activation-enable-refusal')).toContainText('409');
|
|
44
|
+
await expect(page.getByTestId('activation-enable-refusal')).toContainText('UnprovenProviderError');
|
|
45
|
+
});
|
|
46
|
+
When('the owner pays the verification charge with their card', async ({ page }) => {
|
|
47
|
+
await fillCard(page);
|
|
48
|
+
await fillCpf(page);
|
|
49
|
+
await page.getByTestId('activation-pay').click();
|
|
50
|
+
});
|
|
51
|
+
When('the owner pays the verification charge with a refused card', async ({ page }) => {
|
|
52
|
+
await fillCard(page, DECLINE_PAN);
|
|
53
|
+
await fillCpf(page);
|
|
54
|
+
await page.getByTestId('activation-pay').click();
|
|
55
|
+
});
|
|
56
|
+
Then('the provider is proven and receiving sales', async ({ page }) => {
|
|
57
|
+
// VERIFICADO is reserved for a landed charge — the chip's one green word.
|
|
58
|
+
await expect(page.getByTestId('payments-status')).toHaveText('VERIFICADO');
|
|
59
|
+
await expect(salesSwitch(page)).toBeChecked();
|
|
60
|
+
});
|
|
61
|
+
Then('the screen says the cent came back', async ({ page }) => {
|
|
62
|
+
// The refund fact, in the screen's own pt-BR copy.
|
|
63
|
+
await expect(page.getByTestId('activation-refunded')).toContainText('estornado');
|
|
64
|
+
});
|
|
65
|
+
Then("the refusal names the provider's reason", async ({ page }) => {
|
|
66
|
+
await expect(page.getByTestId('activation-error')).toContainText('recusada');
|
|
67
|
+
await expect(page.getByTestId('activation-error')).toContainText('CARD_DECLINED');
|
|
68
|
+
});
|
|
69
|
+
Then('the provider received each attempt as its own charge', async ({ page }) => {
|
|
70
|
+
// Two charges REACHED the provider: a retry that replayed the first
|
|
71
|
+
// refusal would have left this at one.
|
|
72
|
+
await expect(paymentsWorld().wire.providerChargeCount(page)).toHaveText('2');
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=activation.steps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation.steps.js","sourceRoot":"","sources":["../../src/steps/activation.steps.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saved-card-wallet.steps.d.ts","sourceRoot":"","sources":["../../src/steps/saved-card-wallet.steps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { expect } from '@playwright/test';
|
|
2
|
+
import { DECLINE_PAN, fillCard } from '../helpers/checkout.js';
|
|
3
|
+
import { paymentsWorld } from '../world.js';
|
|
4
|
+
import { Given, Then, When } from './fixtures.js';
|
|
5
|
+
/**
|
|
6
|
+
* SAVING A CARD WITHOUT BUYING (FUT-183, over FUT-478's buyer vault rows).
|
|
7
|
+
*
|
|
8
|
+
* A separate file from `carteira.steps.ts` on purpose: that one is the DIGITAL
|
|
9
|
+
* wallets (Google Pay / Apple Pay) — a faster way to pay inside checkout.
|
|
10
|
+
* These steps are the SAVED-CARD wallet: the package's manage-cards surface,
|
|
11
|
+
* reached outside any purchase, where nothing is charged at all.
|
|
12
|
+
*
|
|
13
|
+
* Every Then reads a test id the package's own vault screens render
|
|
14
|
+
* (`manage-cards*`, `add-card*`), plus the shared card form ids — so the
|
|
15
|
+
* journey means the same thing in any host that mounts `screens.ManageCards`.
|
|
16
|
+
* The card the buyer types decides the outcome: the shared `DECLINE_PAN` is
|
|
17
|
+
* the one the stub refuses at validation.
|
|
18
|
+
*/
|
|
19
|
+
Given("the shopper opens the store's card wallet", async ({ page }) => {
|
|
20
|
+
await paymentsWorld().open(page, 'wallet');
|
|
21
|
+
});
|
|
22
|
+
When('she decides to add a card', async ({ page }) => {
|
|
23
|
+
await page.getByTestId('manage-cards-add').click();
|
|
24
|
+
// Wait for the FORM, not merely the click: `/cards/begin` runs in between,
|
|
25
|
+
// and typing into a form that has not mounted is the flake this avoids.
|
|
26
|
+
await expect(page.getByTestId('add-card')).toBeVisible();
|
|
27
|
+
});
|
|
28
|
+
When('she fills in the card and saves it', async ({ page }) => {
|
|
29
|
+
await fillCard(page);
|
|
30
|
+
await page.getByTestId('add-card-save').click();
|
|
31
|
+
});
|
|
32
|
+
When('she tries to save a refused card', async ({ page }) => {
|
|
33
|
+
await fillCard(page, DECLINE_PAN);
|
|
34
|
+
await page.getByTestId('add-card-save').click();
|
|
35
|
+
});
|
|
36
|
+
Then('the card is stored and appears in the list', async ({ page }) => {
|
|
37
|
+
await expect(page.getByTestId('add-card-saved')).toBeVisible();
|
|
38
|
+
await expect(page.getByTestId('manage-cards-list')).toBeVisible();
|
|
39
|
+
await expect(page.getByTestId('manage-cards-empty')).toHaveCount(0);
|
|
40
|
+
});
|
|
41
|
+
Then('the list shows only the brand and the last digits', async ({ page }) => {
|
|
42
|
+
// Display metadata ONLY. The vault token — the thing that can charge —
|
|
43
|
+
// never reaches this screen; what she reads back is brand + last4 + expiry.
|
|
44
|
+
// The quoted strings are the screen's pt-BR product copy, asserted as-is.
|
|
45
|
+
const list = page.getByTestId('manage-cards-list');
|
|
46
|
+
await expect(list).toContainText('••••');
|
|
47
|
+
await expect(list).toContainText('Validade');
|
|
48
|
+
});
|
|
49
|
+
Then('the refusal explains why and the form stays on screen', async ({ page }) => {
|
|
50
|
+
// The endpoint's own reason, and the form kept editable under it — wiping
|
|
51
|
+
// her input to say the card was refused would be the screen working
|
|
52
|
+
// against her. The asserted word is the pt-BR product copy of the reason.
|
|
53
|
+
await expect(page.getByTestId('add-card-error')).toBeVisible();
|
|
54
|
+
await expect(page.getByTestId('add-card-error')).toContainText('cartão');
|
|
55
|
+
await expect(page.getByTestId('card-number')).toBeVisible();
|
|
56
|
+
});
|
|
57
|
+
Then('the wallet still holds no card', async ({ page }) => {
|
|
58
|
+
await expect(page.getByTestId('manage-cards-empty')).toBeVisible();
|
|
59
|
+
await expect(page.getByTestId('manage-cards-list')).toHaveCount(0);
|
|
60
|
+
});
|
|
61
|
+
Then('the empty wallet invites saving the first card', async ({ page }) => {
|
|
62
|
+
await expect(page.getByTestId('manage-cards-empty')).toBeVisible();
|
|
63
|
+
await expect(page.getByTestId('manage-cards-add')).toBeVisible();
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=saved-card-wallet.steps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"saved-card-wallet.steps.js","sourceRoot":"","sources":["../../src/steps/saved-card-wallet.steps.ts"],"names":[],"mappings":"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"}
|
package/dist/world.d.ts
CHANGED
|
@@ -76,6 +76,26 @@ export type PaymentsStore =
|
|
|
76
76
|
* fallback rule — no button, and the card form stays the way to pay.
|
|
77
77
|
*/
|
|
78
78
|
| 'apple-pay-unsupported'
|
|
79
|
+
/**
|
|
80
|
+
* The buyer's saved-card WALLET (FUT-183 over FUT-478), not a checkout: the
|
|
81
|
+
* host opens the package's manage-cards surface at a store whose provider
|
|
82
|
+
* can vault — one mintable chain entry with the vault seam, connected in
|
|
83
|
+
* stub mode — and the wallet starts EMPTY. The card the buyer types decides
|
|
84
|
+
* the outcome: the package's `DECLINE_PAN` is refused at validation, any
|
|
85
|
+
* other valid card is stored. (Not a digital wallet — those are the
|
|
86
|
+
* `google-pay` / `apple-pay` shapes above.)
|
|
87
|
+
*/
|
|
88
|
+
| 'wallet'
|
|
89
|
+
/**
|
|
90
|
+
* A merchant ADMIN surface, not a checkout (FUT-463/FUT-689): the settings
|
|
91
|
+
* screen of ONE provider that declares the activation charge, connected in
|
|
92
|
+
* stub mode and never charged — so the sales switch starts locked off. The
|
|
93
|
+
* host lands the owner on that provider's own panel, whose host-rendered
|
|
94
|
+
* activation step shows the shared card form (`card-number`…, `buyer-cpf`)
|
|
95
|
+
* plus the `activation-*` test ids the steps file documents. The card the
|
|
96
|
+
* owner types decides the outcome, exactly as in the `wallet` shape.
|
|
97
|
+
*/
|
|
98
|
+
| 'activation'
|
|
79
99
|
/** Declares the on-page screen (FUT-596). */
|
|
80
100
|
| 'screen-on-page'
|
|
81
101
|
/** Declares the hand-off screen (FUT-596). */
|
package/dist/world.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"world.d.ts","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"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"}
|
package/dist/world.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"world.js","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"world.js","sourceRoot":"","sources":["../src/world.ts"],"names":[],"mappings":"AA0KA,IAAI,SAAS,GAAyB,IAAI,CAAC;AAE3C;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAoB;IACtD,SAAS,GAAG,KAAK,CAAC;AACpB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,0EAA0E;YACxE,0EAA0E,CAC7E,CAAC;IACJ,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@journey @activation
|
|
2
|
+
Feature: Activating a provider
|
|
3
|
+
|
|
4
|
+
"Connected" and "can charge" are different facts, and the gap between them
|
|
5
|
+
is where a store ships broken: credentials authenticate, the switch flips,
|
|
6
|
+
and the first real shopper is refused. So a provider that declares the
|
|
7
|
+
activation charge EARNS its switch — one cent through the owner's own card,
|
|
8
|
+
on the same rails a shopper's money takes, refunded on the spot — and stays
|
|
9
|
+
off until that cent has landed.
|
|
10
|
+
|
|
11
|
+
Background:
|
|
12
|
+
Given the owner opens the settings of a connected but unproven provider
|
|
13
|
+
|
|
14
|
+
Scenario: Enabling without proof is refused
|
|
15
|
+
Then the sales switch is locked off until a real charge lands
|
|
16
|
+
When the owner tries to force the provider on anyway
|
|
17
|
+
Then the enable request is refused as unproven
|
|
18
|
+
|
|
19
|
+
Scenario: Paying the one-cent verification enables the provider
|
|
20
|
+
When the owner pays the verification charge with their card
|
|
21
|
+
Then the provider is proven and receiving sales
|
|
22
|
+
And the screen says the cent came back
|
|
23
|
+
|
|
24
|
+
Scenario: A refused card names the reason and a retry is a fresh charge
|
|
25
|
+
When the owner pays the verification charge with a refused card
|
|
26
|
+
Then the refusal names the provider's reason
|
|
27
|
+
When the owner pays the verification charge with their card
|
|
28
|
+
Then the provider is proven and receiving sales
|
|
29
|
+
And the provider received each attempt as its own charge
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@journey @saved-cards
|
|
2
|
+
Feature: Saving a card without buying
|
|
3
|
+
|
|
4
|
+
Saving a card is not buying: no order exists, nothing is charged, and the
|
|
5
|
+
card still travels its usual path — the browser mints the token and the
|
|
6
|
+
provider validates it. What the shopper reads back is only what is fit to
|
|
7
|
+
show: the brand and the last digits. The token that can charge stays on the
|
|
8
|
+
store's side and never reaches this screen.
|
|
9
|
+
|
|
10
|
+
There is deliberately no delete button here: taking a card off the list is
|
|
11
|
+
between the store and the provider, not a tap on this screen.
|
|
12
|
+
|
|
13
|
+
Background:
|
|
14
|
+
Given the shopper opens the store's card wallet
|
|
15
|
+
|
|
16
|
+
Scenario: Saving a card without buying anything
|
|
17
|
+
When she decides to add a card
|
|
18
|
+
And she fills in the card and saves it
|
|
19
|
+
Then the card is stored and appears in the list
|
|
20
|
+
And the list shows only the brand and the last digits
|
|
21
|
+
|
|
22
|
+
Scenario: A card refused at validation explains why and stays off the list
|
|
23
|
+
When she decides to add a card
|
|
24
|
+
And she tries to save a refused card
|
|
25
|
+
Then the refusal explains why and the form stays on screen
|
|
26
|
+
And the wallet still holds no card
|
|
27
|
+
|
|
28
|
+
Scenario: The empty wallet invites saving the first card
|
|
29
|
+
Then the empty wallet invites saving the first card
|