Skip to content

Commit

Permalink
Merge pull request #6 from evias/add-qr-abstraction
Browse files Browse the repository at this point in the history
nemtech/NIP#21 : improved unit tests for QR generation and schema definition
  • Loading branch information
AnthonyLaw authored May 2, 2019
2 parents 0ff7146 + 66f4bf2 commit 4293ca3
Show file tree
Hide file tree
Showing 8 changed files with 377 additions and 2 deletions.
4 changes: 3 additions & 1 deletion src/QRCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import {
QRCode as QRCodeImpl,
QR8BitByte,
ErrorCorrectLevel,
} from 'qrcode-generator-ts';

import {
Expand Down Expand Up @@ -81,7 +82,8 @@ export abstract class QRCode implements QRCodeInterface {

// prepare QR generation
const qr = new QRCodeImpl();
qr.setTypeNumber(40);
qr.setTypeNumber(QRCodeSettings.VERSION_NUMBER);
qr.setErrorCorrectLevel(QRCodeSettings.CORRECTION_LEVEL);

// get JSON representation
const json = this.toJSON();
Expand Down
2 changes: 1 addition & 1 deletion src/QRCodeGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,4 @@ export class QRCodeGenerator {
): TransactionQR {
return new TransactionQR(transaction, networkType, chainId);
}
};
}
26 changes: 26 additions & 0 deletions src/QRCodeSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
* See the License for the specific language governing permissions and
*limitations under the License.
*/
import {
ErrorCorrectLevel,
} from 'qrcode-generator-ts';

// internal dependencies
import {QRCodeType} from '../index';

Expand All @@ -24,6 +28,28 @@ import {QRCodeType} from '../index';
*/
export class QRCodeSettings {

/**
* The Error correction level.
*
* @var {ErrorCorrectLevel}
*/
public static CORRECTION_LEVEL = ErrorCorrectLevel.L;

/**
* The QR Code version number.
*
* With `40-L` configuration, the QR Code can contain
* up to `2953` bytes. As defined in the following link,
* this is the maximum storage capacity for our types
* or QR Codes:
*
* https://en.wikipedia.org/wiki/QR_code#Design
*
* @see https://en.wikipedia.org/wiki/QR_code#Design
* @var {string}
*/
public static VERSION_NUMBER = 40;

/**
* The QR Code cell size in pixels.
*
Expand Down
61 changes: 61 additions & 0 deletions test/AccountQR.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Copyright 2019 NEM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
*limitations under the License.
*/
import {expect} from "chai";
import {
Account,
NetworkType,
} from 'nem2-sdk';
import {
QRCode as QRCodeImpl,
QR8BitByte,
ErrorCorrectLevel,
} from 'qrcode-generator-ts';

// internal dependencies
import {
QRCodeInterface,
QRCode,
QRCodeType,
QRCodeSettings,
ContactQR,
} from "../index";

describe('AccountQR -->', () => {

describe('toJSON() should', () => {

it('include mandatory NIP-7 QR Code base fields', () => {
// Arrange:
const account = Account.createFromPrivateKey(
'F97AE23C2A28ECEDE6F8D6C447C0A10B55C92DDE9316CCD36C3177B073906978',
NetworkType.TEST_NET
);

// Act:
const addContact = new ContactQR(account, NetworkType.TEST_NET, '');
const actualJSON = addContact.toJSON();
const actualObject = JSON.parse(actualJSON);

// Assert:
expect(actualObject).to.have.property('v');
expect(actualObject).to.have.property('type');
expect(actualObject).to.have.property('network_id');
expect(actualObject).to.have.property('chain_id');
expect(actualObject).to.have.property('data');
});
});

});
61 changes: 61 additions & 0 deletions test/ContactQR.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* Copyright 2019 NEM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
*limitations under the License.
*/
import {expect} from "chai";
import {
PublicAccount,
NetworkType,
} from 'nem2-sdk';
import {
QRCode as QRCodeImpl,
QR8BitByte,
ErrorCorrectLevel,
} from 'qrcode-generator-ts';

// internal dependencies
import {
QRCodeInterface,
QRCode,
QRCodeType,
QRCodeSettings,
ContactQR,
} from "../index";

describe('ContactQR -->', () => {

describe('toJSON() should', () => {

it('include mandatory NIP-7 QR Code base fields', () => {
// Arrange:
const account = PublicAccount.createFromPublicKey(
'C5C55181284607954E56CD46DE85F4F3EF4CC713CC2B95000FA741998558D268',
NetworkType.TEST_NET
);

// Act:
const addContact = new ContactQR(account, NetworkType.TEST_NET, '');
const actualJSON = addContact.toJSON();
const actualObject = JSON.parse(actualJSON);

// Assert:
expect(actualObject).to.have.property('v');
expect(actualObject).to.have.property('type');
expect(actualObject).to.have.property('network_id');
expect(actualObject).to.have.property('chain_id');
expect(actualObject).to.have.property('data');
});
});

});
149 changes: 149 additions & 0 deletions test/QRCode.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
/**
* Copyright 2019 NEM
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
*limitations under the License.
*/
import {expect} from "chai";
import {
TransferTransaction,
Deadline,
Address,
Mosaic,
NamespaceId,
UInt64,
PlainMessage,
NetworkType,
} from 'nem2-sdk';
import {
QRCode as QRCodeImpl,
QR8BitByte,
ErrorCorrectLevel,
} from 'qrcode-generator-ts';

// internal dependencies
import {
QRCodeInterface,
QRCode,
QRCodeType,
QRCodeSettings,
} from "../index";

/// region Mock for QRCode specialization
// extend abstract class for tests
class FakeQR extends QRCode implements QRCodeInterface {
constructor(
public readonly object: Object,
public readonly networkType: NetworkType,
public readonly chainId: string) {
super(QRCodeType.ExportObject, networkType, chainId);
}

public toJSON(): string {
const jsonSchema = {
'v': 3,
'type': this.type,
'network_id': this.networkType,
'chain_id': this.chainId,
'data': this.object,
};
return JSON.stringify(jsonSchema);
}
}
/// end-region Mock for QRCode specialization

describe('QRCode -->', () => {

describe('toBase64() should', () => {

it('create same Base64 given same objects', () => {
// Arrange:
const object1 = {"test1": "test1"};
const object2 = {"test1": "test1"};

// Act:
const fakeQR1 = new FakeQR(object1, NetworkType.TEST_NET, 'no-chain-id');
const fakeQR2 = new FakeQR(object2, NetworkType.TEST_NET, 'no-chain-id');
const implQR1 = fakeQR1.build();
const implQR2 = fakeQR2.build();

// Assert:
expect(fakeQR1.toBase64()).to.be.equal(fakeQR2.toBase64());
});

it('create different Base64 given different objects', () => {
// Arrange:
const object1 = {"test1": "test1"};
const object2 = {"test2": "test2"};

// Act:
const fakeQR1 = new FakeQR(object1, NetworkType.TEST_NET, 'no-chain-id');
const fakeQR2 = new FakeQR(object2, NetworkType.TEST_NET, 'no-chain-id');
const implQR1 = fakeQR1.build();
const implQR2 = fakeQR2.build();

// Assert:
expect(fakeQR1.toBase64()).to.not.be.equal(fakeQR2.toBase64());
});
});

describe('build() should', () => {

it('set correct settings for QR Code generation', () => {
// Arrange:
const object = {"test": "test"};
const modulesCount = QRCodeSettings.VERSION_NUMBER * 4 + 17;

// Act:
const fakeQR = new FakeQR(object, NetworkType.TEST_NET, 'no-chain-id');
const implQR = fakeQR.build();

// Assert:
expect(implQR.getTypeNumber()).to.be.equal(QRCodeSettings.VERSION_NUMBER);
expect(implQR.getErrorCorrectLevel()).to.be.equal(QRCodeSettings.CORRECTION_LEVEL);
expect(implQR.getModuleCount()).to.be.equal(modulesCount);
});

it('create same QR codes given same objects', () => {
// Arrange:
const object1 = {"test1": "test1"};
const object2 = {"test1": "test1"};

// Act:
const fakeQR1 = new FakeQR(object1, NetworkType.TEST_NET, 'no-chain-id');
const fakeQR2 = new FakeQR(object2, NetworkType.TEST_NET, 'no-chain-id');
const implQR1 = fakeQR1.build();
const implQR2 = fakeQR2.build();

// Assert:
expect(fakeQR1.toJSON()).to.be.equal(fakeQR2.toJSON());
expect(fakeQR1.toBase64()).to.be.equal(fakeQR2.toBase64());
});

it('create different QR codes given different objects', () => {
// Arrange:
const object1 = {"test1": "test1"};
const object2 = {"test2": "test2"};

// Act:
const fakeQR1 = new FakeQR(object1, NetworkType.TEST_NET, 'no-chain-id');
const fakeQR2 = new FakeQR(object2, NetworkType.TEST_NET, 'no-chain-id');
const implQR1 = fakeQR1.build();
const implQR2 = fakeQR2.build();

// Assert:
expect(fakeQR1.toJSON()).to.not.be.equal(fakeQR2.toJSON());
expect(fakeQR1.toBase64()).to.not.be.equal(fakeQR2.toBase64());
});
});

});
3 changes: 3 additions & 0 deletions test/QRCodeGenerator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ describe('QRCodeGenerator -->', () => {
});

describe('createTransactionRequest() should', () => {

//XXX set default TESTNET and CHAIN_ID

it('generate correct Base64 representation for TransferTransaction', () => {
// Arrange:
const transfer = TransferTransaction.create(
Expand Down
Loading

0 comments on commit 4293ca3

Please sign in to comment.