Skip to content

Commit

Permalink
fix(loadLibrary): fix loadLibrary domain validation
Browse files Browse the repository at this point in the history
Add vite for unit testing
Add unit tests
Add github actions yo run unit tests on pipeline

KJS-3329
  • Loading branch information
Iker Navarro committed Nov 15, 2023
1 parent 42dcdcc commit 17f4c9a
Show file tree
Hide file tree
Showing 19 changed files with 1,994 additions and 194 deletions.
16 changes: 14 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: E2E Tests
name: Tests
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
jobs:
test:
test-e2e:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
Expand All @@ -30,3 +30,15 @@ jobs:
name: playwright-report
path: playwright-report/
retention-days: 30
test-unit:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm run test:unit
80 changes: 44 additions & 36 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!-- BACK TO TOP LINK -->
<a id="readme-top"></a>

<a id="readme-top"></a>

<!-- PROJECT SHIELDS -->
<div align="center">
Expand Down Expand Up @@ -37,21 +37,20 @@
</p>
</div>


![SmartForm](./assets/smartform.png)

## About the project

Any payment form must comply with PCI-DSS requirements. A classical integration will be displayed
on the banks page using a redirection. In that case, PCI-DSS requirements are done by your bank.

By using this package Lyra allows to integrate a payment form using standard HTML elements on your
website. This library will load the [Javacript library][doc-home] from Lyra servers transforming
automatically each sensitive field (pan, security code, ...) into an IFrame, allowing to comply with
By using this package Lyra allows to integrate a payment form using standard HTML elements on your
website. This library will load the [Javacript library][doc-home] from Lyra servers transforming
automatically each sensitive field (pan, security code, ...) into an IFrame, allowing to comply with
all regulations.

The **embedded-form-glue** library provides a set of utilities to easily integrate the Payment
form into any we application made with Javascript frameworks like React, Vue, Angular, Svelte,
The **embedded-form-glue** library provides a set of utilities to easily integrate the Payment
form into any we application made with Javascript frameworks like React, Vue, Angular, Svelte,
Ionic, etc.

## Getting Started
Expand All @@ -77,15 +76,17 @@ First, define the theme files to load in the head section of your HTML page:
```html
<head>
(...)
<link rel="stylesheet"
href="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon-reset.css">
<link
rel="stylesheet"
href="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon-reset.css"
/>
<script src="~~CHANGE_ME_ENDPOINT~~/static/js/krypton-client/V4.0/ext/neon.js"></script>
(...)
</head>
```

> **Note**
>
>
> Replace **`~~CHANGE_ME_ENDPOINT~~`** with your configuration endpoint.
For more information about theming, please see [Lyra theming documentation][doc-themes]
Expand All @@ -101,45 +102,44 @@ After that, define the location where the payment form will be generated in your
```

> **Note**
>
> Specifify the element **kr-smart-form** inside the target location to load the Smart Form (any
>
> Specifify the element **kr-smart-form** inside the target location to load the Smart Form (any
> kind of payment method).
### Javascript

Import the library in your javascript file or component with:

```javascript
import KRGlue from "@lyracom/embedded-form-glue";
import KRGlue from '@lyracom/embedded-form-glue'
```

And finally, you can generate the payment form with the following code:

```javascript
/* Integration public key */
const publicKey = '~~CHANGE_ME_PUBLIC_KEY~~';
const publicKey = '~~CHANGE_ME_PUBLIC_KEY~~'
/* Endpoint. Must include the protocol (https://) */
const endPoint = '~~CHANGE_ME_ENDPOINT~~';
const endPoint = '~~CHANGE_ME_ENDPOINT~~'

/* Load the remote library and get the KR object */
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
/* Setting configuration */
await KR.setFormConfig({ 'kr-language': 'en-US' })
/* Attach a payment form to a given DOM selector */
const { result } = await KR.attachForm('#myPaymentForm')
/* Show the payment form */
await KR.showForm(result.formId);
/* Render the payment form into a given DOM selector */
const { result } = await KR.renderElements('#myPaymentForm')
```

> **Note**
>
>
> Replace **`~~CHANGE_ME_PUBLIC_KEY~~`** with your configuration public key.
>
>
> Replace **`~~CHANGE_ME_ENDPOINT~~`** with your configuration endpoint.
> **Warning**
>
> KR methods use Promises. You should always use the **await** keyword or **then method** when
> calling them. Please see [Javascript Promises][js-promises] and [Async Functions][js-async-await]
>
> KR methods use Promises. You should always use the **await** keyword or **then method** when
> calling them. Please see [Javascript Promises][js-promises] and [Async Functions][js-async-await]
> for more information.
## First transaction
Expand All @@ -148,8 +148,8 @@ Once the payment form is set up, you will see the skeleton animation. This is be
using the default demo token. To make a real transaction, you need to get a real **formToken**.

To get a proper test **formToken**, make a request to the Charge/CreatePayment web service. To not
expose your credentials, it is mandatory to do that from a server. Please see the
[NodeJS server example](examples/server/README.md), or visit the following links for more
expose your credentials, it is mandatory to do that from a server. Please see the
[NodeJS server example](examples/server/README.md), or visit the following links for more
information:

- [Embedded form quick start][doc-quick-start]
Expand All @@ -160,10 +160,14 @@ Once you have a **formToken**, you can set it in the payment form with the follo

```javascript
// Use the loadLibrary to set the form token
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey, '~~CHANGE_ME_FORM_TOKEN~~')
const { KR } = await KRGlue.loadLibrary(
endPoint,
publicKey,
'~~CHANGE_ME_FORM_TOKEN~~'
)

// Or set the form token once the library is loaded
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
await KR.setFormConfig({ formToken: '~~CHANGE_ME_FORM_TOKEN~~' })
```

Expand All @@ -178,11 +182,11 @@ methods.

### loadLibrary

Use `loadLibrary` method to load the Lyra Javascript library. The method returns a `Promise` with
Use `loadLibrary` method to load the Lyra Javascript library. The method returns a `Promise` with
the `KR` object.

```javascript
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
const { KR } = await KRGlue.loadLibrary(endPoint, publicKey)
```

## KR object
Expand All @@ -195,7 +199,7 @@ The available methods and callbacks are described in the following sections.
- [KR callbacks](./docs/kr_callbacks.md)

> **Note**
>
>
> See Lyra [Javascript library reference][doc-reference] for the complete reference guide.
## JavaScript frameworks integration
Expand All @@ -221,14 +225,15 @@ The payment form can be customized in many ways. Some of them in the following e
- [Add additional fields](./docs/customization#add-additional-fields)
- [Use a different HTML structure](./docs/customization#use-a-different-html-structure)

Any of these customizations can be done using the same method **KR.attachForm()**.
Any of these customizations can be done using the same method **KR.renderElements()**.

> **Note**
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
> information.
<!-- CONTRIBUTING -->

## Contributing

Contributions are welcome and pull requests will be reviewed and taken into account.
Expand Down Expand Up @@ -260,17 +265,19 @@ npm run examples:serve
Execute the tests with the command:

```bash
npm run test
npm run test:e2e
```

<!-- LICENSE -->

## License

Distributed under the MIT License. See the [LICENSE file](./LICENCE.txt) for more information.

<p align="right">(<a href="#readme-top">back to top</a>)</p>

<!-- MARKDOWN LINKS & IMAGES -->

[build-shield]: https://img.shields.io/circleci/build/github/lyra/embedded-form-glue?style=for-the-badge&logo=github
[build-url]: https://circleci.com/gh/lyra/embedded-form-glue
[npm-shield]: https://img.shields.io/npm/v/@lyracom/embedded-form-glue?style=for-the-badge&logo=npm
Expand All @@ -285,6 +292,7 @@ Distributed under the MIT License. See the [LICENSE file](./LICENCE.txt) for mor
[license-url]: https://github.com/lyra/embedded-form-glue/blob/master/LICENSE.txt

<!-- DOC LINKS -->

[doc-home]: https://docs.lyra.com/en/rest/V4.0/javascript/
[doc-quick-start]: https://docs.lyra.com/en/rest/V4.0/javascript/quick_start_js.html
[doc-reference]: https://docs.lyra.com/en/rest/V4.0/javascript/features/reference.html
Expand Down
14 changes: 11 additions & 3 deletions app/KryptonGlue.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,23 @@ class Glue {
}

loadLibrary(domain, publicKey, formToken = null) {
const domainRegex =
/^(?:http(s)?:\/\/)[\w.-]+(?:\.[\w.-]+)+[\w\-._~:/?#[\]@!$&'()*+,;=.]+$/g
const pubKeyRegex = /^\d{2,8}:(|test)publickey_.+$/g

if (this.loaded) return this.getKrypton(publicKey)
if (!domain) return Promise.reject('Domain not defined')
if (!publicKey) return Promise.reject('Public key not defined')

if (!domainRegex.test(domain)) {
// Domain validation
try {
const domainUrl = new URL(domain)

if (!['http:', 'https:'].includes(domainUrl.protocol))
throw new Error('Invalid protocol')

if (domainUrl.port) throw new Error('No port allowed')
if (domainUrl.search !== '') throw new Error('No query params allowed')
if (domainUrl.pathname !== '/') throw new Error('Invalid path')
} catch (err) {
console.error('Domain format should be https://domain.name')
return Promise.reject(`[${domain}] is not a valid endpoint domain`)
}
Expand Down
14 changes: 7 additions & 7 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The payment form can be customized in many ways like:
<div class="kr-pan"></div>
<div class="kr-expiry"></div>
</div>
</div>
</div>
</div>
```

Expand All @@ -23,7 +23,7 @@ The payment form can be customized in many ways like:
<div class="kr-smart-form">
<div class="kr-embedded">
<div class="kr-pan"></div>
<input
<input
class="kr-theme my-custom-email-field"
type="text"
name="email"
Expand Down Expand Up @@ -57,13 +57,13 @@ The payment form can be customized in many ways like:
</div>
<div class="kr-expiry"></div>
</div>
</div>
</div>
</div>
```

Any of these customizations can be done using the same method **KR.attachForm()**.
Any of these customizations can be done using the same method **KR.renderElements()**.

> **Note**
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
> information.
>
> Please see the [Field Customization][doc-customization] section of the documentation for more
> information.
25 changes: 18 additions & 7 deletions docs/kr_methods.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@

# KR object methods

These are the current available methods to manipulate the payment form:

## attachForm
## renderElements

Render a payment form into a given DOM selector: return a `promise` with the `KR` object and result.

```javascript
const selector = `#myPaymentForm` // DOM selector
const { KR, result } = await KR.renderElements(selector)
```

> **_NOTE:_** if nothing is provided renderElements will search the complete DOM for the supported HTML elements
## attachForm (DEPRECATED use renderElements instead)

Attach a payment form to a given DOM selector: return a `promise` with the `KR` object and result.

Expand All @@ -20,8 +30,9 @@ Add a payment form to a given DOM selector: return a `promise` with the `KR` obj
const selector = `#myPaymentForm` // DOM selector
const { KR, result } = await KR.addForm(selector)
```

> **Warning**
>
>
> Only for cards payment method
## showForm
Expand All @@ -42,7 +53,6 @@ const { result } = await KR.addForm(selector)
const { KR } = await KR.hideForm(result.formId)
```


## setFormConfig

Set the configuration of the payment form on runtime: return a `promise` with the `KR` object.
Expand All @@ -53,8 +63,9 @@ const { KR } = await KR.setFormConfig({
language: `en-US`
})
```

> **Note**
>
>
> Please see the [type definition](../index.d.ts) file for the list of available configuration options.
## validateForm
Expand Down Expand Up @@ -87,7 +98,6 @@ available in the payment form.
const { KR } = await KR.openPaymentMethod('cards')
```


## openPopin

On popin mode, open the payment form in a popin: return a `promise` with the `KR` object.
Expand Down Expand Up @@ -159,10 +169,11 @@ Remove all generated payment forms: return a `promise` with the `KR` object.
```javascript
const { KR } = await KR.removeForms()
```

## removeEventCallbacks

Remove all event callbacks: return a `promise` with the `KR` object.

```javascript
const { KR } = await KR.removeEventCallbacks()
```
```
Loading

0 comments on commit 17f4c9a

Please sign in to comment.