@12-apps/payments-e2e 1.0.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 +112 -0
- package/dist/globs.d.ts +43 -0
- package/dist/globs.d.ts.map +1 -0
- package/dist/globs.js +70 -0
- package/dist/globs.js.map +1 -0
- package/dist/helpers/checkout.d.ts +32 -0
- package/dist/helpers/checkout.d.ts.map +1 -0
- package/dist/helpers/checkout.js +47 -0
- package/dist/helpers/checkout.js.map +1 -0
- package/dist/index.d.ts +42 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +42 -0
- package/dist/index.js.map +1 -0
- package/dist/steps/compra.steps.d.ts +2 -0
- package/dist/steps/compra.steps.d.ts.map +1 -0
- package/dist/steps/compra.steps.js +193 -0
- package/dist/steps/compra.steps.js.map +1 -0
- package/dist/steps/fixtures.d.ts +18 -0
- package/dist/steps/fixtures.d.ts.map +1 -0
- package/dist/steps/fixtures.js +19 -0
- package/dist/steps/fixtures.js.map +1 -0
- package/dist/steps/loja.steps.d.ts +2 -0
- package/dist/steps/loja.steps.d.ts.map +1 -0
- package/dist/steps/loja.steps.js +68 -0
- package/dist/steps/loja.steps.js.map +1 -0
- package/dist/steps/telas.steps.d.ts +2 -0
- package/dist/steps/telas.steps.d.ts.map +1 -0
- package/dist/steps/telas.steps.js +40 -0
- package/dist/steps/telas.steps.js.map +1 -0
- package/dist/world.d.ts +139 -0
- package/dist/world.d.ts.map +1 -0
- package/dist/world.js +25 -0
- package/dist/world.js.map +1 -0
- package/features/a-compra-sobrevive-ao-primeiro-provedor.feature +28 -0
- package/features/a-loja-nao-cobra-online.feature +25 -0
- package/features/a-tela-que-o-provedor-pediu.feature +49 -0
- package/features/comprando-com-cartao.feature +24 -0
- package/features/comprando-com-pix.feature +25 -0
- package/features/pagando-na-pagina-do-provedor.feature +31 -0
- package/features/quando-o-pagamento-nao-vai.feature +40 -0
- package/package.json +42 -0
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# `@12-apps/payments-e2e`
|
|
2
|
+
|
|
3
|
+
The buyer journeys for the payments checkout, as Gherkin you run **against your
|
|
4
|
+
own app**.
|
|
5
|
+
|
|
6
|
+
Mounting `createPaymentFlows` gives you a checkout. This gives you its
|
|
7
|
+
end-to-end coverage: twenty scenarios across seven features — PIX, card, hosted
|
|
8
|
+
hand-off and return, provider failover, issuer declines, an unresolved charge, a
|
|
9
|
+
store that cannot charge at all, and per-provider screens. You implement one
|
|
10
|
+
port and add three lines of config. Nothing is copied, so a scenario added here
|
|
11
|
+
later runs in your app on the next version bump.
|
|
12
|
+
|
|
13
|
+
## Why a port at all
|
|
14
|
+
|
|
15
|
+
The scenarios are portable because every assertion in them reads a test id the
|
|
16
|
+
payments components themselves render — `card-number`, `checkout-method-CARD`,
|
|
17
|
+
`pix-code`, `payment-paid` mean the same thing in every consumer.
|
|
18
|
+
|
|
19
|
+
What is **not** portable is everything around them: how your app routes to a
|
|
20
|
+
checkout, how a merchant of a given shape comes to exist, and where you record
|
|
21
|
+
what crossed the wire. That, and only that, is `PaymentsWorld`.
|
|
22
|
+
|
|
23
|
+
## Wiring it up
|
|
24
|
+
|
|
25
|
+
**1. Implement the port**, in a module inside your own `steps` glob:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
// tests/e2e/steps/payments-world.ts
|
|
29
|
+
import { definePaymentsWorld } from '@12-apps/payments-e2e';
|
|
30
|
+
|
|
31
|
+
definePaymentsWorld({
|
|
32
|
+
// Put the browser on a checkout for a store of this shape.
|
|
33
|
+
open: async (page, store) => { /* route + seed however you do */ },
|
|
34
|
+
raiseHostedPayable: async (page) => { /* …and wait for the interstitial */ },
|
|
35
|
+
returnFromProvider: async (page) => { /* a real return trip */ },
|
|
36
|
+
hostedReturnStatus: (page) => page.getByTestId('…'),
|
|
37
|
+
fixtures: { headProvider, tailProvider, hostedUrlFragment, payableRef, taxId },
|
|
38
|
+
wire: { paths, chargeKeys, chargeBody, tokensByProvider, providerCharges, providerChargeCount, navigated },
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
It must live in the `steps` glob because playwright-bdd imports every step file
|
|
43
|
+
before the first `Given` runs — that is what registers the world in every
|
|
44
|
+
worker.
|
|
45
|
+
|
|
46
|
+
**2. Point your bdd config at the package:**
|
|
47
|
+
|
|
48
|
+
```ts
|
|
49
|
+
import { paymentsFeatures, paymentsFeaturesRoot, paymentsSteps } from '@12-apps/payments-e2e';
|
|
50
|
+
|
|
51
|
+
const journeys = defineBddConfig({
|
|
52
|
+
features: [paymentsFeatures, 'tests/e2e/features/**/*.feature'],
|
|
53
|
+
featuresRoot: paymentsFeaturesRoot,
|
|
54
|
+
steps: [paymentsSteps, 'tests/e2e/steps/**/*.ts'],
|
|
55
|
+
outputDir: '.features-gen',
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Keep your own `steps` glob in the list — that is where your
|
|
60
|
+
`definePaymentsWorld` call lives.
|
|
61
|
+
|
|
62
|
+
### Three things that fail SILENTLY if you get them wrong
|
|
63
|
+
|
|
64
|
+
These are not style notes. Each one produces a **green run with zero journeys**,
|
|
65
|
+
which is worse than a red one.
|
|
66
|
+
|
|
67
|
+
- **Use the exported globs, not hand-written `node_modules/…` paths.** pnpm's
|
|
68
|
+
store is nested and a workspace link is not a directory you can guess. A glob
|
|
69
|
+
that matches nothing makes bddgen compile what it found — nothing — and the
|
|
70
|
+
run passes.
|
|
71
|
+
- **Set `featuresRoot`.** bddgen mirrors each feature's path relative to it. Left
|
|
72
|
+
unset, specs compile to `.features-gen/node_modules/@12-apps/payments-e2e/…`,
|
|
73
|
+
and Playwright's default `testIgnore` drops every path containing
|
|
74
|
+
`node_modules`. Seven features compiled, zero collected, green.
|
|
75
|
+
- **Assert your journey count.** Whatever the mechanism, put a check somewhere
|
|
76
|
+
that the number of scenarios you expect actually ran.
|
|
77
|
+
|
|
78
|
+
## `PaymentsStore` — the shapes a scenario asks for
|
|
79
|
+
|
|
80
|
+
A scenario names a kind of merchant; you decide how to produce one. A harness
|
|
81
|
+
declares a provider chain in-page; a real storefront seeds a tenant. The feature
|
|
82
|
+
files do not change either way.
|
|
83
|
+
|
|
84
|
+
`pix-only` · `card` · `both-methods` · `hosted` · `awaiting` · `settles` ·
|
|
85
|
+
`declined` · `unresolved` · `unavailable` · `no-provider` ·
|
|
86
|
+
`no-provider-remedy` · `payments-off` · `two-mintable` · `redirect-head` ·
|
|
87
|
+
`screen-on-page` · `screen-handoff` · `screen-undeclared` · `screen-unknown`
|
|
88
|
+
|
|
89
|
+
Adding a member is a breaking change for hosts, deliberately: a scenario needing
|
|
90
|
+
a store nobody can build is a scenario that silently never runs.
|
|
91
|
+
|
|
92
|
+
## Why this package ships compiled JavaScript
|
|
93
|
+
|
|
94
|
+
Its siblings export raw `.ts` through their `exports` map, because an
|
|
95
|
+
application's **bundler** consumes them and transpiles whatever it is pointed
|
|
96
|
+
at. These files are loaded by **Node** — your `playwright.config.ts` imports
|
|
97
|
+
this module and bddgen imports the step files — and Node refuses to strip types
|
|
98
|
+
from anything under `node_modules`
|
|
99
|
+
(`ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`). Playwright's own TS transform
|
|
100
|
+
does not rescue them either; it skips `node_modules` by design.
|
|
101
|
+
|
|
102
|
+
Shipping source here would produce a package that type-checks, publishes,
|
|
103
|
+
installs, and then throws on your first test run.
|
|
104
|
+
|
|
105
|
+
## Writing your own specs in the same vocabulary
|
|
106
|
+
|
|
107
|
+
The buyer gestures are exported too, so hand-written specs beside the journeys
|
|
108
|
+
read the same way:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { fillCard, payCard, reachPayment, VALID_CPF } from '@12-apps/payments-e2e';
|
|
112
|
+
```
|
package/dist/globs.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** Every packaged `.feature`, for `defineBddConfig({ features })`. */
|
|
2
|
+
export declare const paymentsFeatures: string;
|
|
3
|
+
/**
|
|
4
|
+
* The base `defineBddConfig({ featuresRoot })` must be given, and it is NOT
|
|
5
|
+
* optional decoration.
|
|
6
|
+
*
|
|
7
|
+
* bddgen mirrors each feature's path RELATIVE TO `featuresRoot` under
|
|
8
|
+
* `outputDir`. Left unset it defaults to the config's own directory, so a
|
|
9
|
+
* feature living in `node_modules/@12-apps/payments-e2e/features/x.feature`
|
|
10
|
+
* compiles to `.features-gen/node_modules/@12-apps/payments-e2e/features/
|
|
11
|
+
* x.feature.spec.js` — a path Playwright then IGNORES, because its default
|
|
12
|
+
* `testIgnore` excludes `**\/node_modules/**`.
|
|
13
|
+
*
|
|
14
|
+
* The result is the worst kind of green: bddgen reports seven features
|
|
15
|
+
* compiled, Playwright collects zero specs from them, and the run passes with
|
|
16
|
+
* the whole packaged suite silently absent. Pointing `featuresRoot` here makes
|
|
17
|
+
* the specs land flat in `outputDir`, where they are collected.
|
|
18
|
+
*/
|
|
19
|
+
export declare const paymentsFeaturesRoot: string;
|
|
20
|
+
/**
|
|
21
|
+
* Every packaged step definition, for `defineBddConfig({ steps })`.
|
|
22
|
+
*
|
|
23
|
+
* COMPILED JavaScript, and that is the reason this package has a build step at
|
|
24
|
+
* all while its siblings ship raw `.ts` through their `exports` map. Those are
|
|
25
|
+
* consumed by an application's BUNDLER, which transpiles whatever it is
|
|
26
|
+
* pointed at. These are loaded by NODE — `playwright.config.ts` imports this
|
|
27
|
+
* module, and bddgen imports the step files — and Node refuses to strip types
|
|
28
|
+
* from anything under `node_modules`:
|
|
29
|
+
*
|
|
30
|
+
* ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING
|
|
31
|
+
*
|
|
32
|
+
* Playwright's own TS transform does not rescue them either; it skips
|
|
33
|
+
* `node_modules` by design. Shipping `src/**\/*.ts` here produces a package
|
|
34
|
+
* that type-checks, publishes, installs, and then throws on the consumer's
|
|
35
|
+
* first test run.
|
|
36
|
+
*
|
|
37
|
+
* The host's own steps glob must ALSO be listed — that is where its
|
|
38
|
+
* `definePaymentsWorld` call lives, and playwright-bdd imports every step file
|
|
39
|
+
* before any scenario runs, which is what makes the registration land in time
|
|
40
|
+
* in every worker.
|
|
41
|
+
*/
|
|
42
|
+
export declare const paymentsSteps: string;
|
|
43
|
+
//# sourceMappingURL=globs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globs.d.ts","sourceRoot":"","sources":["../src/globs.ts"],"names":[],"mappings":"AA8BA,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,EAAE,MAAqD,CAAC;AAErF;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,oBAAoB,EAAE,MAAwC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,aAAa,EAAE,MAAkD,CAAC"}
|
package/dist/globs.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { dirname, join } from 'node:path';
|
|
3
|
+
/**
|
|
4
|
+
* Where this package's features and steps live, ON DISK, in the consumer's
|
|
5
|
+
* `node_modules` (FUT-561).
|
|
6
|
+
*
|
|
7
|
+
* `defineBddConfig` takes filesystem globs, not module specifiers — it hands
|
|
8
|
+
* them to a glob matcher, so `'@12-apps/payments-e2e/features/**'` matches
|
|
9
|
+
* nothing and, worse, matches nothing SILENTLY: bddgen compiles the features it
|
|
10
|
+
* found, finds none, and the run is green with zero journeys.
|
|
11
|
+
*
|
|
12
|
+
* So the paths are RESOLVED here instead of written down by every consumer.
|
|
13
|
+
* A host that hard-codes `node_modules/@12-apps/payments-e2e/...` is broken by
|
|
14
|
+
* pnpm's nested store, by a workspace link, and by this package's own layout
|
|
15
|
+
* changing; resolving from the package's own entry point is correct under all
|
|
16
|
+
* three.
|
|
17
|
+
*/
|
|
18
|
+
const require_ = createRequire(import.meta.url);
|
|
19
|
+
/**
|
|
20
|
+
* The package root, found from a file this package definitely exports.
|
|
21
|
+
*
|
|
22
|
+
* `./package.json` is exported precisely so this lookup needs no guess about
|
|
23
|
+
* directory depth — see the `exports` map.
|
|
24
|
+
*/
|
|
25
|
+
function packageRoot() {
|
|
26
|
+
return dirname(require_.resolve('@12-apps/payments-e2e/package.json'));
|
|
27
|
+
}
|
|
28
|
+
/** Every packaged `.feature`, for `defineBddConfig({ features })`. */
|
|
29
|
+
export const paymentsFeatures = join(packageRoot(), 'features/**/*.feature');
|
|
30
|
+
/**
|
|
31
|
+
* The base `defineBddConfig({ featuresRoot })` must be given, and it is NOT
|
|
32
|
+
* optional decoration.
|
|
33
|
+
*
|
|
34
|
+
* bddgen mirrors each feature's path RELATIVE TO `featuresRoot` under
|
|
35
|
+
* `outputDir`. Left unset it defaults to the config's own directory, so a
|
|
36
|
+
* feature living in `node_modules/@12-apps/payments-e2e/features/x.feature`
|
|
37
|
+
* compiles to `.features-gen/node_modules/@12-apps/payments-e2e/features/
|
|
38
|
+
* x.feature.spec.js` — a path Playwright then IGNORES, because its default
|
|
39
|
+
* `testIgnore` excludes `**\/node_modules/**`.
|
|
40
|
+
*
|
|
41
|
+
* The result is the worst kind of green: bddgen reports seven features
|
|
42
|
+
* compiled, Playwright collects zero specs from them, and the run passes with
|
|
43
|
+
* the whole packaged suite silently absent. Pointing `featuresRoot` here makes
|
|
44
|
+
* the specs land flat in `outputDir`, where they are collected.
|
|
45
|
+
*/
|
|
46
|
+
export const paymentsFeaturesRoot = join(packageRoot(), 'features');
|
|
47
|
+
/**
|
|
48
|
+
* Every packaged step definition, for `defineBddConfig({ steps })`.
|
|
49
|
+
*
|
|
50
|
+
* COMPILED JavaScript, and that is the reason this package has a build step at
|
|
51
|
+
* all while its siblings ship raw `.ts` through their `exports` map. Those are
|
|
52
|
+
* consumed by an application's BUNDLER, which transpiles whatever it is
|
|
53
|
+
* pointed at. These are loaded by NODE — `playwright.config.ts` imports this
|
|
54
|
+
* module, and bddgen imports the step files — and Node refuses to strip types
|
|
55
|
+
* from anything under `node_modules`:
|
|
56
|
+
*
|
|
57
|
+
* ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING
|
|
58
|
+
*
|
|
59
|
+
* Playwright's own TS transform does not rescue them either; it skips
|
|
60
|
+
* `node_modules` by design. Shipping `src/**\/*.ts` here produces a package
|
|
61
|
+
* that type-checks, publishes, installs, and then throws on the consumer's
|
|
62
|
+
* first test run.
|
|
63
|
+
*
|
|
64
|
+
* The host's own steps glob must ALSO be listed — that is where its
|
|
65
|
+
* `definePaymentsWorld` call lives, and playwright-bdd imports every step file
|
|
66
|
+
* before any scenario runs, which is what makes the registration land in time
|
|
67
|
+
* in every worker.
|
|
68
|
+
*/
|
|
69
|
+
export const paymentsSteps = join(packageRoot(), 'dist/steps/**/*.js');
|
|
70
|
+
//# sourceMappingURL=globs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"globs.js","sourceRoot":"","sources":["../src/globs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;;;;;;;;;;GAcG;AACH,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEhD;;;;;GAKG;AACH,SAAS,WAAW;IAClB,OAAO,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,oCAAoC,CAAC,CAAC,CAAC;AACzE,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAW,IAAI,CAAC,WAAW,EAAE,EAAE,uBAAuB,CAAC,CAAC;AAErF;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAW,IAAI,CAAC,WAAW,EAAE,EAAE,UAAU,CAAC,CAAC;AAE5E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAW,IAAI,CAAC,WAAW,EAAE,EAAE,oBAAoB,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type Page } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* The three or four gestures every checkout spec repeats (FUT-743, packaged by
|
|
4
|
+
* FUT-561).
|
|
5
|
+
*
|
|
6
|
+
* Deliberately thin. Anything that DECIDES something — which method, which
|
|
7
|
+
* store, what the wire should say — stays in the spec, so a spec still reads as
|
|
8
|
+
* the thing it asserts. What lives here is only the typing.
|
|
9
|
+
*
|
|
10
|
+
* Every one of these drives a test id the PAYMENTS PACKAGE itself renders, so
|
|
11
|
+
* they mean the same thing in any app that mounts the checkout — which is why
|
|
12
|
+
* they ship rather than being reimplemented per consumer. Opening a page and
|
|
13
|
+
* choosing a store do NOT live here: those are the host's, and they are the
|
|
14
|
+
* whole of `PaymentsWorld`.
|
|
15
|
+
*/
|
|
16
|
+
/** A CPF that passes the real check-digit rule, which is what the form runs. */
|
|
17
|
+
export declare const VALID_CPF = "529.982.247-25";
|
|
18
|
+
/** A PAN that passes Luhn. Under stub mode it mints a fake token locally. */
|
|
19
|
+
export declare const GOOD_PAN = "4111 1111 1111 1111";
|
|
20
|
+
/** The sandbox PAN that always declines, honoured by the shipped tokenizer. */
|
|
21
|
+
export declare const DECLINE_PAN = "4000 0000 0000 0002";
|
|
22
|
+
/** Fill the Dados step's CPF. */
|
|
23
|
+
export declare function fillCpf(page: Page, cpf?: string): Promise<void>;
|
|
24
|
+
/** Fill the card form the store's chain gave the buyer. */
|
|
25
|
+
export declare function fillCard(page: Page, pan?: string): Promise<void>;
|
|
26
|
+
/** Pick the card tile on a store that offers both, and wait for the form. */
|
|
27
|
+
export declare function chooseCard(page: Page): Promise<void>;
|
|
28
|
+
/** Press the pay bar and wait for the submit to have actually left. */
|
|
29
|
+
export declare function payCard(page: Page): Promise<void>;
|
|
30
|
+
/** Walk the Dados step and land on Pagamento. */
|
|
31
|
+
export declare function reachPayment(page: Page): Promise<void>;
|
|
32
|
+
//# sourceMappingURL=checkout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../../src/helpers/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AAEH,gFAAgF;AAChF,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAE1C,6EAA6E;AAC7E,eAAO,MAAM,QAAQ,wBAAwB,CAAC;AAE9C,+EAA+E;AAC/E,eAAO,MAAM,WAAW,wBAAwB,CAAC;AAEjD,iCAAiC;AACjC,wBAAsB,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAEhF;AAED,2DAA2D;AAC3D,wBAAsB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,GAAE,MAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKhF;AAED,6EAA6E;AAC7E,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAG1D;AAED,uEAAuE;AACvE,wBAAsB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAEvD;AAED,iDAAiD;AACjD,wBAAsB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAG5D"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { expect } from '@playwright/test';
|
|
2
|
+
/**
|
|
3
|
+
* The three or four gestures every checkout spec repeats (FUT-743, packaged by
|
|
4
|
+
* FUT-561).
|
|
5
|
+
*
|
|
6
|
+
* Deliberately thin. Anything that DECIDES something — which method, which
|
|
7
|
+
* store, what the wire should say — stays in the spec, so a spec still reads as
|
|
8
|
+
* the thing it asserts. What lives here is only the typing.
|
|
9
|
+
*
|
|
10
|
+
* Every one of these drives a test id the PAYMENTS PACKAGE itself renders, so
|
|
11
|
+
* they mean the same thing in any app that mounts the checkout — which is why
|
|
12
|
+
* they ship rather than being reimplemented per consumer. Opening a page and
|
|
13
|
+
* choosing a store do NOT live here: those are the host's, and they are the
|
|
14
|
+
* whole of `PaymentsWorld`.
|
|
15
|
+
*/
|
|
16
|
+
/** A CPF that passes the real check-digit rule, which is what the form runs. */
|
|
17
|
+
export const VALID_CPF = '529.982.247-25';
|
|
18
|
+
/** A PAN that passes Luhn. Under stub mode it mints a fake token locally. */
|
|
19
|
+
export const GOOD_PAN = '4111 1111 1111 1111';
|
|
20
|
+
/** The sandbox PAN that always declines, honoured by the shipped tokenizer. */
|
|
21
|
+
export const DECLINE_PAN = '4000 0000 0000 0002';
|
|
22
|
+
/** Fill the Dados step's CPF. */
|
|
23
|
+
export async function fillCpf(page, cpf = VALID_CPF) {
|
|
24
|
+
await page.getByTestId('buyer-cpf').fill(cpf);
|
|
25
|
+
}
|
|
26
|
+
/** Fill the card form the store's chain gave the buyer. */
|
|
27
|
+
export async function fillCard(page, pan = GOOD_PAN) {
|
|
28
|
+
await page.getByTestId('card-number').fill(pan);
|
|
29
|
+
await page.getByTestId('card-holder').fill('ANA COMPRADORA');
|
|
30
|
+
await page.getByTestId('card-expiry').fill('12/31');
|
|
31
|
+
await page.getByTestId('card-cvv').fill('123');
|
|
32
|
+
}
|
|
33
|
+
/** Pick the card tile on a store that offers both, and wait for the form. */
|
|
34
|
+
export async function chooseCard(page) {
|
|
35
|
+
await page.getByTestId('checkout-method-CARD').click();
|
|
36
|
+
await expect(page.getByTestId('card-view')).toBeVisible();
|
|
37
|
+
}
|
|
38
|
+
/** Press the pay bar and wait for the submit to have actually left. */
|
|
39
|
+
export async function payCard(page) {
|
|
40
|
+
await page.getByTestId('card-pay').click();
|
|
41
|
+
}
|
|
42
|
+
/** Walk the Dados step and land on Pagamento. */
|
|
43
|
+
export async function reachPayment(page) {
|
|
44
|
+
await fillCpf(page);
|
|
45
|
+
await page.getByTestId('checkout-continue').click();
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=checkout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"checkout.js","sourceRoot":"","sources":["../../src/helpers/checkout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAa,MAAM,kBAAkB,CAAC;AAErD;;;;;;;;;;;;;GAaG;AAEH,gFAAgF;AAChF,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAE1C,6EAA6E;AAC7E,MAAM,CAAC,MAAM,QAAQ,GAAG,qBAAqB,CAAC;AAE9C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,WAAW,GAAG,qBAAqB,CAAC;AAEjD,iCAAiC;AACjC,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAU,EAAE,MAAc,SAAS;IAC/D,MAAM,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,2DAA2D;AAC3D,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAU,EAAE,MAAc,QAAQ;IAC/D,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAChD,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7D,MAAM,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpD,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACjD,CAAC;AAED,6EAA6E;AAC7E,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAU;IACzC,MAAM,IAAI,CAAC,WAAW,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,CAAC;IACvD,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;AAC5D,CAAC;AAED,uEAAuE;AACvE,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAU;IACtC,MAAM,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED,iDAAiD;AACjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAU;IAC3C,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpB,MAAM,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC,KAAK,EAAE,CAAC;AACtD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@12-apps/payments-e2e` — the buyer journeys, shipped (FUT-561).
|
|
3
|
+
*
|
|
4
|
+
* A host that mounts the payments checkout inherits its end-to-end coverage by
|
|
5
|
+
* implementing one port and adding two globs. Nothing is copied, so a scenario
|
|
6
|
+
* added to the library later runs in every consumer on the next version bump.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* // <your app>/tests/e2e/steps/payments-world.ts — inside your `steps` glob
|
|
10
|
+
* import { definePaymentsWorld } from '@12-apps/payments-e2e';
|
|
11
|
+
*
|
|
12
|
+
* definePaymentsWorld({
|
|
13
|
+
* open: async (page, store) => { ... },
|
|
14
|
+
* raiseHostedPayable: async (page) => { ... },
|
|
15
|
+
* returnFromProvider: async (page) => { ... },
|
|
16
|
+
* hostedReturnStatus: (page) => page.getByTestId('...'),
|
|
17
|
+
* fixtures: { ... },
|
|
18
|
+
* wire: { ... },
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* // playwright.config.ts
|
|
24
|
+
* defineBddConfig({
|
|
25
|
+
* features: ['tests/e2e/features/**\/*.feature', paymentsFeatures],
|
|
26
|
+
* steps: ['tests/e2e/steps/**\/*.ts', paymentsSteps],
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* The globs are exported rather than documented as strings so a consumer never
|
|
31
|
+
* has to know this package's internal layout — and cannot be broken by it
|
|
32
|
+
* moving.
|
|
33
|
+
*/
|
|
34
|
+
export { definePaymentsWorld, paymentsWorld, type PaymentsFixtures, type PaymentsStore, type PaymentsWireProbe, type PaymentsWorld, } from './world.js';
|
|
35
|
+
export { paymentsFeatures, paymentsFeaturesRoot, paymentsSteps } from './globs.js';
|
|
36
|
+
/**
|
|
37
|
+
* The buyer gestures the packaged steps are built from, exported so a host can
|
|
38
|
+
* write its OWN specs in the same vocabulary. Every one drives a test id the
|
|
39
|
+
* payments components render, so they are as portable as the journeys.
|
|
40
|
+
*/
|
|
41
|
+
export { chooseCard, DECLINE_PAN, fillCard, fillCpf, GOOD_PAN, payCard, reachPayment, VALID_CPF, } from './helpers/checkout.js';
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EACL,mBAAmB,EACnB,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEnF;;;;GAIG;AACH,OAAO,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,SAAS,GACV,MAAM,uBAAuB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@12-apps/payments-e2e` — the buyer journeys, shipped (FUT-561).
|
|
3
|
+
*
|
|
4
|
+
* A host that mounts the payments checkout inherits its end-to-end coverage by
|
|
5
|
+
* implementing one port and adding two globs. Nothing is copied, so a scenario
|
|
6
|
+
* added to the library later runs in every consumer on the next version bump.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* // <your app>/tests/e2e/steps/payments-world.ts — inside your `steps` glob
|
|
10
|
+
* import { definePaymentsWorld } from '@12-apps/payments-e2e';
|
|
11
|
+
*
|
|
12
|
+
* definePaymentsWorld({
|
|
13
|
+
* open: async (page, store) => { ... },
|
|
14
|
+
* raiseHostedPayable: async (page) => { ... },
|
|
15
|
+
* returnFromProvider: async (page) => { ... },
|
|
16
|
+
* hostedReturnStatus: (page) => page.getByTestId('...'),
|
|
17
|
+
* fixtures: { ... },
|
|
18
|
+
* wire: { ... },
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ```ts
|
|
23
|
+
* // playwright.config.ts
|
|
24
|
+
* defineBddConfig({
|
|
25
|
+
* features: ['tests/e2e/features/**\/*.feature', paymentsFeatures],
|
|
26
|
+
* steps: ['tests/e2e/steps/**\/*.ts', paymentsSteps],
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* The globs are exported rather than documented as strings so a consumer never
|
|
31
|
+
* has to know this package's internal layout — and cannot be broken by it
|
|
32
|
+
* moving.
|
|
33
|
+
*/
|
|
34
|
+
export { definePaymentsWorld, paymentsWorld, } from './world.js';
|
|
35
|
+
export { paymentsFeatures, paymentsFeaturesRoot, paymentsSteps } from './globs.js';
|
|
36
|
+
/**
|
|
37
|
+
* The buyer gestures the packaged steps are built from, exported so a host can
|
|
38
|
+
* write its OWN specs in the same vocabulary. Every one drives a test id the
|
|
39
|
+
* payments components render, so they are as portable as the journeys.
|
|
40
|
+
*/
|
|
41
|
+
export { chooseCard, DECLINE_PAN, fillCard, fillCpf, GOOD_PAN, payCard, reachPayment, VALID_CPF, } from './helpers/checkout.js';
|
|
42
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,OAAO,EACL,mBAAmB,EACnB,aAAa,GAKd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEnF;;;;GAIG;AACH,OAAO,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,OAAO,EACP,YAAY,EACZ,SAAS,GACV,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compra.steps.d.ts","sourceRoot":"","sources":["../../src/steps/compra.steps.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { expect } from '@playwright/test';
|
|
2
|
+
import { DECLINE_PAN, fillCard, payCard, reachPayment } from '../helpers/checkout.js';
|
|
3
|
+
import { paymentsWorld } from '../world.js';
|
|
4
|
+
import { Then, When } from './fixtures.js';
|
|
5
|
+
/**
|
|
6
|
+
* WHAT THE BUYER DOES, and what she is owed for it (FUT-743).
|
|
7
|
+
*
|
|
8
|
+
* The Thens are split between two kinds of assertion on purpose, and both kinds
|
|
9
|
+
* matter:
|
|
10
|
+
*
|
|
11
|
+
* - what is ON THE SCREEN — the QR, the receipt, the absence of a pay bar;
|
|
12
|
+
* - what actually CROSSED THE WIRE — the charge body's own keys, the CPF the
|
|
13
|
+
* provider received, how many instruments the chain carried.
|
|
14
|
+
*
|
|
15
|
+
* The second kind is the reason these journeys exist at all. FUT-740 passed
|
|
16
|
+
* fifteen green checks with three criticals live, every one of them in the seam
|
|
17
|
+
* between the published client and the published mount, and not one of them
|
|
18
|
+
* visible to a test that only looked at a screen.
|
|
19
|
+
*/
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
// The buyer's own gestures
|
|
22
|
+
// ---------------------------------------------------------------------------
|
|
23
|
+
When('ela informa o CPF e segue para o pagamento', async ({ page }) => {
|
|
24
|
+
await reachPayment(page);
|
|
25
|
+
});
|
|
26
|
+
When('ela escolhe pagar com cartão', async ({ page }) => {
|
|
27
|
+
// Deliberately does NOT wait for the card form: in a store that hands the
|
|
28
|
+
// buyer over there will never be one, and that is a scenario of its own.
|
|
29
|
+
await page.getByTestId('checkout-method-CARD').click();
|
|
30
|
+
});
|
|
31
|
+
When('ela paga com um cartão novo', async ({ page }) => {
|
|
32
|
+
await fillCard(page);
|
|
33
|
+
await payCard(page);
|
|
34
|
+
});
|
|
35
|
+
When('ela paga com um cartão recusado', async ({ page }) => {
|
|
36
|
+
await fillCard(page, DECLINE_PAN);
|
|
37
|
+
await payCard(page);
|
|
38
|
+
});
|
|
39
|
+
When('a loja gera o pagamento hospedado', async ({ page }) => {
|
|
40
|
+
// The host raises the payable however it does — a button here, a real cart
|
|
41
|
+
// elsewhere — and is responsible for waiting until the interstitial has
|
|
42
|
+
// MOUNTED, not merely until the click landed. Parking the order is an effect
|
|
43
|
+
// of that screen mounting, and a scenario that navigates away before it has
|
|
44
|
+
// is testing a trip whose outbound leg never happened.
|
|
45
|
+
await paymentsWorld().raiseHostedPayable(page);
|
|
46
|
+
});
|
|
47
|
+
When('ela volta da página do provedor', async ({ page }) => {
|
|
48
|
+
// The way a hosted provider really sends her back: the host's own return
|
|
49
|
+
// route, plus the markers the provider appends. The application was destroyed
|
|
50
|
+
// in between, so only what was parked before leaving survives.
|
|
51
|
+
await paymentsWorld().returnFromProvider(page);
|
|
52
|
+
});
|
|
53
|
+
// ---------------------------------------------------------------------------
|
|
54
|
+
// What she sees
|
|
55
|
+
// ---------------------------------------------------------------------------
|
|
56
|
+
Then('só a opção PIX é oferecida', async ({ page }) => {
|
|
57
|
+
await expect(page.getByTestId('checkout-method-PIX')).toBeVisible();
|
|
58
|
+
await expect(page.getByTestId('checkout-method-CARD')).toHaveCount(0);
|
|
59
|
+
});
|
|
60
|
+
Then('ela vê o QR code do PIX', async ({ page }) => {
|
|
61
|
+
await expect(page.getByTestId('pix-view')).toBeVisible();
|
|
62
|
+
await expect(page.getByTestId('pix-qr')).toBeVisible();
|
|
63
|
+
});
|
|
64
|
+
Then('o código copia-e-cola veio do provedor', async ({ page }) => {
|
|
65
|
+
await expect(page.getByTestId('pix-code')).toContainText('BR.GOV.BCB.PIX');
|
|
66
|
+
});
|
|
67
|
+
Then('ela vê o formulário de cartão', async ({ page }) => {
|
|
68
|
+
await expect(page.getByTestId('card-view')).toBeVisible();
|
|
69
|
+
});
|
|
70
|
+
Then('nenhum formulário de cartão é mostrado', async ({ page }) => {
|
|
71
|
+
await expect(page.getByTestId('card-view')).toHaveCount(0);
|
|
72
|
+
await expect(page.getByTestId('card-number')).toHaveCount(0);
|
|
73
|
+
});
|
|
74
|
+
Then('o pagamento é confirmado', async ({ page }) => {
|
|
75
|
+
await expect(page.getByTestId('payment-paid')).toBeVisible();
|
|
76
|
+
});
|
|
77
|
+
Then('o recibo mostra o valor pago', async ({ page }) => {
|
|
78
|
+
await expect(page.getByTestId('payment-receipt')).toBeVisible();
|
|
79
|
+
await expect(page.getByTestId('payment-amount')).toHaveText('R$ 75,00');
|
|
80
|
+
});
|
|
81
|
+
Then('o pagamento falha', async ({ page }) => {
|
|
82
|
+
await expect(page.getByTestId('payment-failed')).toBeVisible();
|
|
83
|
+
});
|
|
84
|
+
Then('ela pode tentar novamente', async ({ page }) => {
|
|
85
|
+
await expect(page.getByTestId('payment-retry')).toBeVisible();
|
|
86
|
+
});
|
|
87
|
+
Then('ela é avisada de que o pagamento está sendo confirmado', async ({ page }) => {
|
|
88
|
+
// Warning tone, not danger. Some provider may be holding her money.
|
|
89
|
+
await expect(page.getByTestId('card-unresolved')).toBeVisible();
|
|
90
|
+
});
|
|
91
|
+
Then('não existe nenhum botão de pagar na tela', async ({ page }) => {
|
|
92
|
+
// REMOVED, not disabled: a disabled control becomes live again on the next
|
|
93
|
+
// render, and a live "Pagar R$ …" under "não pague de novo" is what a thumb
|
|
94
|
+
// reaches for.
|
|
95
|
+
await expect(page.getByTestId('card-pay-bar')).toHaveCount(0);
|
|
96
|
+
await expect(page.getByTestId('card-pay')).toHaveCount(0);
|
|
97
|
+
});
|
|
98
|
+
Then('não existe nenhum botão de tentar novamente na tela', async ({ page }) => {
|
|
99
|
+
await expect(page.getByTestId('payment-retry')).toHaveCount(0);
|
|
100
|
+
await expect(page.getByTestId('checkout-retry-payment')).toHaveCount(0);
|
|
101
|
+
});
|
|
102
|
+
Then('o erro do cartão menciona o outro meio de pagamento', async ({ page }) => {
|
|
103
|
+
await expect(page.getByTestId('card-error')).toContainText('cartão');
|
|
104
|
+
await expect(page.getByTestId('card-error')).toContainText('PIX');
|
|
105
|
+
});
|
|
106
|
+
Then('a opção PIX continua na tela', async ({ page }) => {
|
|
107
|
+
await expect(page.getByTestId('checkout-method-PIX')).toBeVisible();
|
|
108
|
+
});
|
|
109
|
+
Then('ela é avisada de que a loja não cobra online', async ({ page }) => {
|
|
110
|
+
await expect(page.getByTestId('checkout-payments-disabled')).toBeVisible();
|
|
111
|
+
});
|
|
112
|
+
Then('ela recebe a opção de chamar o garçom', async ({ page }) => {
|
|
113
|
+
await expect(page.getByTestId('checkout-payments-remedy')).toBeVisible();
|
|
114
|
+
await expect(page.getByTestId('checkout-payments-remedy-action')).toBeVisible();
|
|
115
|
+
});
|
|
116
|
+
Then('nenhuma forma de pagamento é oferecida', async ({ page }) => {
|
|
117
|
+
await expect(page.getByTestId('checkout-method')).toHaveCount(0);
|
|
118
|
+
await expect(page.getByTestId('card-view')).toHaveCount(0);
|
|
119
|
+
await expect(page.getByTestId('pix-view')).toHaveCount(0);
|
|
120
|
+
});
|
|
121
|
+
Then('ela vê a tela de transferência para o provedor', async ({ page }) => {
|
|
122
|
+
await expect(page.getByTestId('checkout-hosted-handoff')).toBeVisible();
|
|
123
|
+
});
|
|
124
|
+
Then('existe um link visível para a página do provedor', async ({ page }) => {
|
|
125
|
+
// A REAL anchor, not a second scripted navigation: when the scripted one was
|
|
126
|
+
// blocked, another one will be too.
|
|
127
|
+
const link = page.getByTestId('checkout-hosted-link');
|
|
128
|
+
await expect(link).toBeVisible();
|
|
129
|
+
// `toHaveAttribute` with a STRING demands the whole value; the host only
|
|
130
|
+
// knows a fragment of the URL its provider mints, so this stays a substring
|
|
131
|
+
// match — escaped, because the fragment is a hostname and its dots must not
|
|
132
|
+
// become wildcards.
|
|
133
|
+
await expect(link).toHaveAttribute('href', new RegExp(paymentsWorld().fixtures.hostedUrlFragment.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')));
|
|
134
|
+
});
|
|
135
|
+
Then('o pagamento volta confirmado', async ({ page }) => {
|
|
136
|
+
await expect(paymentsWorld().hostedReturnStatus(page)).toHaveText('PAID');
|
|
137
|
+
});
|
|
138
|
+
// ---------------------------------------------------------------------------
|
|
139
|
+
// What actually crossed
|
|
140
|
+
// ---------------------------------------------------------------------------
|
|
141
|
+
Then('nenhum pedido chegou a ser criado', async ({ page }) => {
|
|
142
|
+
// The config read is the only request there is. A store that cannot charge
|
|
143
|
+
// must not have a payable brought into existence.
|
|
144
|
+
await expect(paymentsWorld().wire.paths(page)).toHaveText('GET /api/checkout/config');
|
|
145
|
+
});
|
|
146
|
+
Then('a cobrança enviada ao provedor carrega o cartão e o CPF dela', async ({ page }) => {
|
|
147
|
+
// What the PROVIDER received, not what the client recorded sending. The wire
|
|
148
|
+
// facts below are written on the way OUT of the published client, so they can
|
|
149
|
+
// only fail if the CLIENT changes; this line is the one that fails if the
|
|
150
|
+
// MOUNT stops reading the flat body — the instrument then reads
|
|
151
|
+
// `(no-instrument)` and the charge was never payable at all.
|
|
152
|
+
const { fixtures, wire } = paymentsWorld();
|
|
153
|
+
await expect(wire.providerCharges(page)).toContainText(`${fixtures.headProvider}:CARD:${fixtures.taxId}:tok:`);
|
|
154
|
+
});
|
|
155
|
+
Then('o corpo da cobrança é o formato plano que o cliente publicado envia', async ({ page }) => {
|
|
156
|
+
const { wire } = paymentsWorld();
|
|
157
|
+
const keys = wire.chargeKeys(page);
|
|
158
|
+
await expect(keys).toContainText('orderId');
|
|
159
|
+
await expect(keys).toContainText('token');
|
|
160
|
+
await expect(keys).toContainText('taxId');
|
|
161
|
+
await expect(wire.chargeBody(page)).not.toContainText('"card"');
|
|
162
|
+
});
|
|
163
|
+
Then('nenhum tokensByProvider é enviado', async ({ page }) => {
|
|
164
|
+
await expect(paymentsWorld().wire.tokensByProvider(page)).toHaveText('(absent)');
|
|
165
|
+
});
|
|
166
|
+
Then('um instrumento foi gerado para cada provedor da cadeia', async ({ page }) => {
|
|
167
|
+
const { fixtures, wire } = paymentsWorld();
|
|
168
|
+
await expect(wire.tokensByProvider(page)).toHaveText(`${fixtures.headProvider},${fixtures.tailProvider}`);
|
|
169
|
+
});
|
|
170
|
+
Then('os dois provedores receberam a cobrança', async ({ page }) => {
|
|
171
|
+
const { fixtures, wire } = paymentsWorld();
|
|
172
|
+
await expect(wire.providerChargeCount(page)).toHaveText('2');
|
|
173
|
+
await expect(wire.providerCharges(page)).toContainText(`${fixtures.tailProvider}:CARD`);
|
|
174
|
+
await expect(wire.providerCharges(page)).toContainText(`${fixtures.headProvider}:CARD`);
|
|
175
|
+
});
|
|
176
|
+
Then('o mapa de instrumentos traz só o provedor que gera token', async ({ page }) => {
|
|
177
|
+
// Sent even though exactly one instrument minted, because the PUBLISHED chain
|
|
178
|
+
// has two entries. Counting the map instead drops it, and the server then
|
|
179
|
+
// reads the bare token as the head's and refuses the entry that needed none.
|
|
180
|
+
await expect(paymentsWorld().wire.tokensByProvider(page)).toHaveText(paymentsWorld().fixtures.headProvider);
|
|
181
|
+
});
|
|
182
|
+
Then('a loja registrou para onde ela seria levada', async ({ page }) => {
|
|
183
|
+
const { fixtures, wire } = paymentsWorld();
|
|
184
|
+
await expect(wire.navigated(page)).toContainText(fixtures.hostedUrlFragment);
|
|
185
|
+
});
|
|
186
|
+
Then('o pedido foi guardado antes da navegação', async ({ page }) => {
|
|
187
|
+
// Reading storage is the only way to see "BEFORE". The navigation may tear
|
|
188
|
+
// the application down at any point after it starts, so a write that happens
|
|
189
|
+
// afterwards never happens at all.
|
|
190
|
+
const parked = await page.evaluate(() => window.sessionStorage.getItem('futurepay.checkout.hostedOrder'));
|
|
191
|
+
expect(parked).toContain(paymentsWorld().fixtures.payableRef);
|
|
192
|
+
});
|
|
193
|
+
//# sourceMappingURL=compra.steps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compra.steps.js","sourceRoot":"","sources":["../../src/steps/compra.steps.ts"],"names":[],"mappings":"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"}
|