Skip to content

Commit

Permalink
Merge branch 'master' into CandidateCheck
Browse files Browse the repository at this point in the history
  • Loading branch information
skodamarthi authored Sep 25, 2020
2 parents 472fa40 + 8ed7a47 commit b7ec471
Show file tree
Hide file tree
Showing 8 changed files with 588 additions and 166 deletions.
4 changes: 4 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@

...

## Which issue does this PR relate to?

...

## Checklist

[ ] Tests are written and maintain or improve code coverage
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ const timezoneHeader = fraudHeaders.get('Gov-Client-Timezone');
const timezoneHeader = fraudHeaders.get(fraudPreventionHeadersEnum.TIMEZONE);
```

## Demo
You can find a demo of the project [here](https://github.com/reubenae/user-data-demo)

## Contributing

1. Fork the repo
Expand Down
1 change: 1 addition & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {extends: ['@commitlint/config-conventional']}
8 changes: 5 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
},
"husky": {
"hooks": {
"pre-push": "npm test && npm run test:coverage"
"pre-push": "npm test && npm run test:coverage",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
},
"lint-staged": {
Expand Down Expand Up @@ -54,17 +55,18 @@
"uuid": "^3.3.3"
},
"devDependencies": {
"@commitlint/cli": "^11.0.0",
"@commitlint/config-conventional": "^11.0.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.1.0",
"eslint": "^7.4.0",
"husky": "^4.2.5",
"husky": "^4.3.0",
"jest": "^26.0.1",
"jest-cli": "^26.1.0",
"jest-coverage-badges": "^1.1.2",
"lint-staged": "^10.2.11",
"prettier": "^2.0.5",
"react-addons-test-utils": "^15.6.2",
"sinon": "^7.5.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12"
},
Expand Down
19 changes: 10 additions & 9 deletions src/js/hmrc/README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
Tax Authority in UK (HMRC) requires software providers using some of their APIs (Eg: MTD VAT API) to provide consistent headers known as Fraud Prevention headers as part of the request. These are HTTP headers that help HMRC to monitor and audit transactions to protect taxpayers’ data from fraudulent activities.
Tax Authority in UK (HMRC) requires software providers using some of their APIs (Eg: MTD VAT API) to provide consistent headers known as Fraud Prevention headers as part of the request. These are HTTP headers that help HMRC to monitor and audit transactions to protect taxpayers’ data from fraudulent activities.
Details here: <https://developer.service.hmrc.gov.uk/api-documentation/docs/fraud-prevention>

Fraud prevention headers submitted by an application are expected to meet the requirements of HMRC’s fraud prevention specification.

Here are some of HMRC's fraud prevention headers for which the values can be generated using this library in the format that HMRC expects:
Here are some of HMRC's fraud prevention headers required to be sent by web applications, for which the values can be generated using this library in the format that HMRC expects:

1. Gov-Client-Timezone
1. Gov-Client-Screens
1. Gov-Client-Window-Size
1. Gov-Client-Browser-Plugins
1. Gov-Client-Browser-Do-Not-Track
1. Gov-Client-Local-IPs
1. Gov-Client-Timezone (The local timezone of the originating device, expressed as UTC±)
1. Gov-Client-Screens (Originating device’s screen details like width, height, scaling-factor, colour-depth)
1. Gov-Client-Window-Size (Originating device’s window width and height)
1. Gov-Client-Browser-Plugins (A list of browser plugins on the originating device)
1. Gov-Client-Browser-Do-Not-Track (Indicates whether 'Do Not Track option' is enabled on the browser)
1. Gov-Client-Local-IPs (A list of all local IPv4 and IPv6 addresses available to the originating device)

Information about these headers can be found here: <https://developer.service.hmrc.gov.uk/api-documentation/docs/fraud-prevention>
Detailed information about each of these headers can be found here: https://developer.service.hmrc.gov.uk/guides/fraud-prevention/connection-method/web-app-via-server/
45 changes: 20 additions & 25 deletions tests/unit/common/browserInfoHelper.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import sinon from "sinon";
import getMockBrowserPluginDetails from "../mock/MockData";
import {
MockRTCPeerConnection,
Expand All @@ -24,10 +23,8 @@ import {
import moment from "moment";

describe("BrowserInfoHelper", () => {
const spies = sinon.createSandbox();

afterEach(() => {
spies.restore();
jest.resetAllMocks();
});

describe("getBrowserDoNotTrackStatus", () => {
Expand Down Expand Up @@ -87,8 +84,8 @@ describe("BrowserInfoHelper", () => {
getBrowserDoNotTrackStatusTests.forEach(
({ test, mockWindow = {}, mockNavigator = {}, expected } = {}) => {
it(test, () => {
spies.stub(globalsUtil, "getWindow").returns(mockWindow);
spies.stub(globalsUtil, "getNavigator").returns(mockNavigator);
jest.spyOn(globalsUtil, "getWindow").mockReturnValue(mockWindow);
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue(mockNavigator);
expect(getBrowserDoNotTrackStatus()).toEqual(expected);
});
}
Expand All @@ -104,42 +101,42 @@ describe("BrowserInfoHelper", () => {
};
});
it("getBrowserPluginsAsString no plugins", () => {
spies.stub(globalsUtil, "getNavigator").returns(mockNavigator);
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue(mockNavigator);
expect(getBrowserPluginsAsString()).toEqual("");
});

it("getBrowserPluginsAsString two plugins", () => {
mockNavigator = {
plugins: getMockBrowserPluginDetails(),
};
spies.stub(globalsUtil, "getNavigator").returns(mockNavigator);
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue(mockNavigator);
expect(getBrowserPluginsAsString()).toEqual("ABC Plugin,XYZ Plugin");
});

it("getBrowserPluginsAsString two plugins and a null plugin", () => {
mockNavigator = {
plugins: [...getMockBrowserPluginDetails(), null],
};
spies.stub(globalsUtil, "getNavigator").returns(mockNavigator);
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue(mockNavigator);
expect(getBrowserPluginsAsString()).toEqual("ABC Plugin,XYZ Plugin");
});
});

describe("getDeviceLocalIPAsString", () => {
let webRtcConnectionStub;
beforeEach(() => {
webRtcConnectionStub = spies.stub(globalsUtil, "getWebRTCConnection");
webRtcConnectionStub = jest.spyOn(globalsUtil, "getWebRTCConnection");
resetDeviceIpString();
});

afterEach(() => {
spies.restore();
jest.restoreAllMocks();
resetDeviceIpString();
resetCandidateString();
});

it("RTCPeerConnection undefined", async () => {
webRtcConnectionStub.returns(undefined);
webRtcConnectionStub.mockReturnValue(undefined);
try {
await getDeviceLocalIPAsString();
} catch (error) {
Expand All @@ -150,7 +147,7 @@ describe("BrowserInfoHelper", () => {
});

it("RTCPeerConnection non constructable", async () => {
webRtcConnectionStub.returns({});
webRtcConnectionStub.mockReturnValue({});
try {
await getDeviceLocalIPAsString();
} catch (error) {
Expand All @@ -161,7 +158,7 @@ describe("BrowserInfoHelper", () => {
});

it("RTCPeerConnection throws CREATE_CONNECTION_ERROR", async() => {
webRtcConnectionStub.returns(MockErrorRTCPeerConnection);
webRtcConnectionStub.mockReturnValue(MockErrorRTCPeerConnection);
try {
await getDeviceLocalIPAsString();
} catch (error) {
Expand All @@ -175,7 +172,7 @@ describe("BrowserInfoHelper", () => {

it("RTCPeerConnection throws NO_IP_FOUND if candidate string does not have valid IP address as 5th element", async () => {
setCandidateString("abc xyz 127.0.0.1");
webRtcConnectionStub.returns(MockRTCPeerConnection);
webRtcConnectionStub.mockReturnValue(MockRTCPeerConnection);
try {
await getDeviceLocalIPAsString();
} catch (error) {
Expand All @@ -187,7 +184,7 @@ describe("BrowserInfoHelper", () => {

it("RTCPeerConnection throws NO_IP_FOUND for empty candidate string", async () => {
setEmptyCandidateString();
webRtcConnectionStub.returns(MockRTCPeerConnection);
webRtcConnectionStub.mockReturnValue(MockRTCPeerConnection);

try {
await getDeviceLocalIPAsString();
Expand All @@ -199,7 +196,7 @@ describe("BrowserInfoHelper", () => {
});

it("RTCPeerConnection valid", async () => {
webRtcConnectionStub.returns(MockRTCPeerConnection);
webRtcConnectionStub.mockReturnValue(MockRTCPeerConnection);
expect(await getDeviceLocalIPAsString()).toEqual("127.0.0.1");
//Calling the function to return an already calculated deviceIpString
expect(await getDeviceLocalIPAsString()).toEqual("127.0.0.1");
Expand All @@ -209,25 +206,23 @@ describe("BrowserInfoHelper", () => {
setCandidateString(
"abc xyz 123 567 789 777 127.0.0.1 randomstring somestring"
);
webRtcConnectionStub.returns(MockRTCPeerConnection);
webRtcConnectionStub.mockReturnValue(MockRTCPeerConnection);
expect(await getDeviceLocalIPAsString()).toEqual("789");
});
});

it("getMTDTaxReturnWithParameter", async () => {
spies.stub(globalsUtil, "getNavigator").returns({
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue({
plugins: getMockBrowserPluginDetails(),
doNotTrack: "yes",
});
spies
.stub(globalsUtil, "getWebRTCConnection")
.returns(MockRTCPeerConnection);
spies.stub(globalsUtil, "getWindow").returns({
jest.spyOn(globalsUtil, "getWebRTCConnection").mockReturnValue(MockRTCPeerConnection);
jest.spyOn(globalsUtil, "getWindow").mockReturnValue({
devicePixelRatio: 2,
innerWidth: 1009,
innerHeight: 1013,
});
spies.stub(globalsUtil, "getScreen").returns({
jest.spyOn(globalsUtil, "getScreen").mockReturnValue({
width: 1019,
height: 1021,
colorDepth: 17,
Expand All @@ -245,7 +240,7 @@ describe("BrowserInfoHelper", () => {
});

it("getScreen", async () => {
spies.stub(globalsUtil, "getScreen").returns({
jest.spyOn(globalsUtil, "getScreen").mockReturnValue({
width: "900px",
height: 1021,
colorDepth: 17,
Expand Down
26 changes: 10 additions & 16 deletions tests/unit/hmrc/mtdFraudPrevention.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import sinon from "sinon";
import getMockBrowserPluginDetails from "../mock/MockData";
import { getFraudPreventionHeaders } from "../../../src/js";
import {
Expand All @@ -12,30 +11,27 @@ import { resetDeviceIpString } from "../../../src/js/common/browserInfoHelper";
import moment from "moment";

describe("FraudPreventionHeaders", () => {
const spies = sinon.createSandbox();
resetDeviceIpString();
resetCandidateString();

afterEach(() => {
spies.restore();
jest.resetAllMocks();
resetDeviceIpString();
resetCandidateString();
});
it("getFraudPreventionHeaders with no errors", async () => {
spies.stub(globalsUtil, "getNavigator").returns({
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue({
plugins: getMockBrowserPluginDetails(),
doNotTrack: "yes",
});
setAdditionalCandidateString(",127.0.0.2");
spies
.stub(globalsUtil, "getWebRTCConnection")
.returns(MockRTCPeerConnection);
spies.stub(globalsUtil, "getWindow").returns({
jest.spyOn(globalsUtil, "getWebRTCConnection").mockReturnValue(MockRTCPeerConnection);
jest.spyOn(globalsUtil, "getWindow").mockReturnValue({
devicePixelRatio: 2,
innerWidth: 1009,
innerHeight: 1013,
});
spies.stub(globalsUtil, "getScreen").returns({
jest.spyOn(globalsUtil, "getScreen").mockReturnValue({
width: 1019,
height: 1021,
colorDepth: 17,
Expand All @@ -60,25 +56,23 @@ describe("FraudPreventionHeaders", () => {
expect(headers.get("Gov-Client-Local-IPs")).toBe("127.0.0.1,127.0.0.2");
});
it("getFraudPreventionHeaders with one error", async () => {
spies.stub(globalsUtil, "getNavigator").returns({
jest.spyOn(globalsUtil, "getNavigator").mockReturnValue({
plugins: getMockBrowserPluginDetails(),
doNotTrack: "yes",
});
setAdditionalCandidateString(",127.0.0.2");
spies
.stub(globalsUtil, "getWebRTCConnection")
.returns(MockRTCPeerConnection);
spies.stub(globalsUtil, "getWindow").returns({
jest.spyOn(globalsUtil, "getWebRTCConnection").mockReturnValue(MockRTCPeerConnection);
jest.spyOn(globalsUtil, "getWindow").mockReturnValue({
devicePixelRatio: 2,
innerWidth: 1009,
innerHeight: 1013,
});
spies.stub(globalsUtil, "getScreen").returns({
jest.spyOn(globalsUtil, "getScreen").mockReturnValue({
width: 1019,
height: 1021,
colorDepth: 17,
});
spies.stub(browserInfoHelper, "getDeviceLocalIPAsString").returns(Promise.reject("Something went wrong."))
jest.spyOn(browserInfoHelper, "getDeviceLocalIPAsString").mockReturnValue(Promise.reject("Something went wrong."));

const {headers, errors} = await getFraudPreventionHeaders();
expect(headers.size).toBe(5);
Expand Down
Loading

0 comments on commit b7ec471

Please sign in to comment.