Skip to content

Commit

Permalink
feat: PAYMENTS-221 Post data as HTML form data
Browse files Browse the repository at this point in the history
  • Loading branch information
davidchin committed Apr 5, 2017
1 parent 914661f commit c0012a6
Show file tree
Hide file tree
Showing 16 changed files with 3,559 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .babelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"presets": ["es2015"]
}
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false
15 changes: 15 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"env": {
"browser": true,
"es6": true,
"jasmine": true
},
"extends": "airbnb-base",
"rules": {
"indent": [2, 4],
"import/prefer-default-export": 0,
"max-len": 0,
"no-param-reassign": ["error", { "props": false }],
"no-use-before-define": [2, "nofunc"]
}
}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.nyc_output
*.log
coverage
node_modules
8 changes: 8 additions & 0 deletions .jasmine.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"spec_dir": "test",
"spec_files": [
"**/*.spec.js"
],
"stopSpecOnExpectationFailure": false,
"random": false
}
7 changes: 7 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*.log
**/.*
bower.json
coverage
docs
node_modules
test
12 changes: 12 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
language: node_js

node_js:
- 4.5.0

cache:
yarn: true
directories:
- node_modules

script:
- npm run test
16 changes: 16 additions & 0 deletions bower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"name": "form-poster",
"version": "1.0.0",
"description": "A JavaScript library for posting HTML form data",
"main": "lib/index.js",
"private": true,
"ignore": [
"*.log",
"**/.*",
"package.json",
"coverage",
"docs",
"node_modules",
"test"
]
}
32 changes: 32 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"name": "form-poster",
"version": "0.0.0",
"description": "A JavaScript library for posting HTML form data",
"main": "lib/index.js",
"private": true,
"repository": {
"type": "git",
"url": "[email protected]:bigcommerce-labs/form-poster-js.git"
},
"scripts": {
"prebuild": "rm -rf lib && npm test",
"build": "NODE_ENV=production babel src --out-dir lib --source-maps",
"changelog": "conventional-changelog --preset angular --infile CHANGELOG.md --same-file",
"coverage": "nyc --reporter text --reporter lcov npm test",
"lint": "eslint src test",
"prepublish": "npm run build",
"pretest": "npm run lint",
"test": "JASMINE_CONFIG_PATH=.jasmine.json babel-node node_modules/.bin/jasmine"
},
"devDependencies": {
"babel-cli": "^6.24.0",
"babel-preset-es2015": "^6.24.0",
"conventional-changelog-cli": "^1.3.1",
"eslint": "^3.18.0",
"eslint-config-airbnb-base": "^11.1.2",
"eslint-plugin-import": "^2.2.0",
"jasmine": "^2.5.3",
"jsdom": "^9.12.0",
"nyc": "^10.2.0"
}
}
39 changes: 39 additions & 0 deletions src/create-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Create input
* @param {string} value
* @param {string} key
* @returns {HTMLInputElement}
*/
function createInput(value, key) {
const input = document.createElement('input');

input.setAttribute('name', key);
input.setAttribute('type', 'hidden');
input.setAttribute('value', value);

return input;
}

/**
* Create form
* @param {string} url
* @param {Object} data
* @returns {HTMLFormElement}
*/
export default function createForm(url, data) {
const form = document.createElement('form');

form.style.display = 'none';

form.setAttribute('action', url);
form.setAttribute('method', 'POST');
form.setAttribute('target', '_top');

Object.keys(data).forEach((key) => {
const value = data[key];

form.appendChild(createInput(value, key));
});

return form;
}
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as postForm } from './post-form';
23 changes: 23 additions & 0 deletions src/post-form.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import createForm from './create-form';

/**
* Post form
* @param {string} url
* @param {Object} data
* @param {Function} [callback]
* @returns {void}
*/
export default function postForm(url, data, callback = () => {}) {
const form = createForm(url, data);

// Some browsers require the form to be part of DOM in order to submit
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);

window.addEventListener('beforeunload', function handleBeforeUnload() {
window.removeEventListener('beforeunload', handleBeforeUnload);

callback();
});
}
41 changes: 41 additions & 0 deletions test/create-form.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import jsdom from 'jsdom';
import createForm from '../src/create-form';

describe('createForm', () => {
let actionUrl;
let fields;

beforeAll(() => {
const document = jsdom.jsdom();

global.window = document.defaultView;
global.document = document;
});

afterAll(() => {
global.window.close();

global.window = null;
global.document = null;
});

beforeEach(() => {
actionUrl = '/pay/initialize';
fields = {
field_1: 'foo',
field_2: 'bar',
};
});

it('should return form with input fields', () => {
const output = createForm(actionUrl, fields);
const expectedOutput = (
'<form style="display: none;" action="/pay/initialize" method="POST" target="_top">' +
'<input name="field_1" type="hidden" value="foo">' +
'<input name="field_2" type="hidden" value="bar">' +
'</form>'
);

expect(output.outerHTML).toEqual(expectedOutput);
});
});
3 changes: 3 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const context = require.context('.', true, /\.spec$/);

context.keys().forEach(context);
46 changes: 46 additions & 0 deletions test/post-form.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import jsdom from 'jsdom';
import * as createFormModule from '../src/create-form';
import postForm from '../src/post-form';

describe('postForm', () => {
let actionUrl;
let data;
let form;

beforeAll(() => {
const document = jsdom.jsdom();

global.window = document.defaultView;
global.document = document;
});

afterAll(() => {
global.window.close();

global.window = null;
global.document = null;
});

beforeEach(() => {
actionUrl = '/pay/initialize';
data = { id: 'adyen' };
form = document.createElement('form');

spyOn(createFormModule, 'default').and.returnValue(form);
spyOn(form, 'submit');
});

it('should create form', () => {
const createForm = createFormModule.default;

postForm(actionUrl, data);

expect(createForm).toHaveBeenCalledWith(actionUrl, data);
});

it('should submit form', () => {
postForm(actionUrl, data);

expect(form.submit).toHaveBeenCalled();
});
});
Loading

0 comments on commit c0012a6

Please sign in to comment.