@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.
Files changed (41) hide show
  1. package/README.md +112 -0
  2. package/dist/globs.d.ts +43 -0
  3. package/dist/globs.d.ts.map +1 -0
  4. package/dist/globs.js +70 -0
  5. package/dist/globs.js.map +1 -0
  6. package/dist/helpers/checkout.d.ts +32 -0
  7. package/dist/helpers/checkout.d.ts.map +1 -0
  8. package/dist/helpers/checkout.js +47 -0
  9. package/dist/helpers/checkout.js.map +1 -0
  10. package/dist/index.d.ts +42 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +42 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/steps/compra.steps.d.ts +2 -0
  15. package/dist/steps/compra.steps.d.ts.map +1 -0
  16. package/dist/steps/compra.steps.js +193 -0
  17. package/dist/steps/compra.steps.js.map +1 -0
  18. package/dist/steps/fixtures.d.ts +18 -0
  19. package/dist/steps/fixtures.d.ts.map +1 -0
  20. package/dist/steps/fixtures.js +19 -0
  21. package/dist/steps/fixtures.js.map +1 -0
  22. package/dist/steps/loja.steps.d.ts +2 -0
  23. package/dist/steps/loja.steps.d.ts.map +1 -0
  24. package/dist/steps/loja.steps.js +68 -0
  25. package/dist/steps/loja.steps.js.map +1 -0
  26. package/dist/steps/telas.steps.d.ts +2 -0
  27. package/dist/steps/telas.steps.d.ts.map +1 -0
  28. package/dist/steps/telas.steps.js +40 -0
  29. package/dist/steps/telas.steps.js.map +1 -0
  30. package/dist/world.d.ts +139 -0
  31. package/dist/world.d.ts.map +1 -0
  32. package/dist/world.js +25 -0
  33. package/dist/world.js.map +1 -0
  34. package/features/a-compra-sobrevive-ao-primeiro-provedor.feature +28 -0
  35. package/features/a-loja-nao-cobra-online.feature +25 -0
  36. package/features/a-tela-que-o-provedor-pediu.feature +49 -0
  37. package/features/comprando-com-cartao.feature +24 -0
  38. package/features/comprando-com-pix.feature +25 -0
  39. package/features/pagando-na-pagina-do-provedor.feature +31 -0
  40. package/features/quando-o-pagamento-nao-vai.feature +40 -0
  41. 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
+ ```
@@ -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"}
@@ -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,2 @@
1
+ export {};
2
+ //# sourceMappingURL=compra.steps.d.ts.map
@@ -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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"}