diff --git a/CHANGELOG.md b/CHANGELOG.md index f0db9a1a..14a68f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,9 +23,10 @@ Feature release including multi-hook support, improved UX for off chain token ho - TS interface custom view -### Performance Improvements +### Performance / Quality Improvements - Reduced the duplication of variable definitions (moved to a common constants file). +- Increased unit test coverage **Full Change log**: diff --git a/README.md b/README.md index 1e82a5d0..0634e0c4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # `token-negotiator` -Token Negotiator enables you build web experiences for users around the tokens they hold. +Open source technology that enables you build web experiences for users around the tokens they hold. ## Usage diff --git a/package.json b/package.json index 7ac3aaff..dbc1c9e6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@tokenscript/token-negotiator", "version": "3.2.0", - "description": "Token-negotiator a token attestation bridge between web 2.0 and 3.0.", + "description": "Open source technology that enables you build web experiences for users around the tokens they hold.", "module": "dist/index.js", "types": "dist/index.d.ts", "files": [ diff --git a/src/__tests__/index.spec.ts b/src/__tests__/index.spec.ts new file mode 100644 index 00000000..e332377a --- /dev/null +++ b/src/__tests__/index.spec.ts @@ -0,0 +1,7 @@ +import { Client } from '../index' + +describe('src spec', () => { + test('ensure client is defined', async () => { + expect(Client).toBeDefined() + }) +}) diff --git a/src/client/__tests__/client.spec.ts b/src/client/__tests__/client.spec.ts index 2d390ca6..1ecae022 100644 --- a/src/client/__tests__/client.spec.ts +++ b/src/client/__tests__/client.spec.ts @@ -1,17 +1,11 @@ // @ts-nocheck import { AbstractAuthentication } from '../auth/abstractAuthentication' -import { AttestedAddress } from '../auth/attestedAddress' import { Client } from '../index' import { TicketZKProof } from '../auth/ticketZKProof' -import { URLNS } from '../../core/messaging' -import { Outlet, defaultConfig } from '../../outlet/index' -import { Client as client_2_0, Outlet as outlet_2_0 } from 'tn2_0' -import { Client as client_2_2, Outlet as outlet_2_2 } from 'tn2_2' import { OffChainTokenConfig } from '../interface' +import { TextEncoder, TextDecoder } from 'util'; -function delay(time) { - return new Promise((resolve) => setTimeout(resolve, time)) -} +Object.assign(global, { TextDecoder, TextEncoder }); let tokenIssuer: OffChainTokenConfig = { collectionID: 'devcon', @@ -27,37 +21,8 @@ let tokenIssuer: OffChainTokenConfig = { base64attestorPubKey: '', } -let tokenIssuer2: OffChainTokenConfig = { - collectionID: 'edcon', - title: 'Devcon', - onChain: false, - tokenOrigin: 'http://some.url/', - attestationOrigin: 'https://stage.attestation.id/', - unEndPoint: 'https://crypto-verify.herokuapp.com/use-devcon-ticket', - image: 'https://raw.githubusercontent.com/TokenScript/token-negotiator/main/mock-images/devcon.svg', - base64senderPublicKeys: { - 10: 'MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAGJAHCiHbrCNAY9fAMdom4dGD6v/KkTIgRCkwLCjXFTkXWGrCEXHaZ8kWwdqlu0oYCrNQ2vdlqOl0s26/LzO8A==|MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAGJAHCiHbrCNAY9fAMdom4dGD6v/KkTIgRCkwLCjXFTkXWGrCEXHaZ8kWwdqlu0oYCrNQ2vdlqOl0s26/LzO8B==', - }, - base64attestorPubKey: '', -} - -let tokenIssuer3: OffChainTokenConfig = { - collectionID: 'devconnect', - title: 'Devcon', - onChain: false, - tokenOrigin: 'http://some.url/', - attestationOrigin: 'https://stage.attestation.id/', - unEndPoint: 'https://crypto-verify.herokuapp.com/use-devcon-ticket', - image: 'https://raw.githubusercontent.com/TokenScript/token-negotiator/main/mock-images/devcon.svg', - base64senderPublicKeys: { - 55: 'MFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEAGJAHCiHbrCNAY9fAMdom4dGD6v/KkTIgRCkwLCjXFTkXWGrCEXHaZ8kWwdqlu0oYCrNQ2vdlqOl0s26/LzO8A==', - }, - base64attestorPubKey: '', -} - const config = { type: 'passive', - // requred to force redirect mode for Client 2.2 enableOffChainRedirectMode: true, issuers: [tokenIssuer], } @@ -126,6 +91,7 @@ class LocalStorageMock { } describe('client spec', () => { + test('tokenNegotiatorClient a failed new instance of client - missing issuers key', () => { let client = new Client({ type: 'passive', @@ -137,6 +103,54 @@ describe('client spec', () => { }) }) + test('client library interface method switch theme can be used', () => { + const tokenNegotiatorClient = getOffChainConfigClient() + let client = new Client({ + type: 'active', + issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(), + options: {}, + }) + client.negotiate().then(() => { + client.switchTheme('dark'); + }); + }) + + test('client library can add token via magic link', () => { + const tokenNegotiatorClient = getOffChainConfigClient() + let client = new Client({ + type: 'active', + issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(), + options: {}, + }) + client.negotiate().then(() => { + client.addTokenViaMagicLink('https://outlet-stage.brandconnector.io/#type=asn&ticket=MIGTME0MATYCAgTUAgECBEEEDoIoocY3CRCPqbHzou84M7C-cWAfzrTnPwz7qWGWv3UVn53jWeTG8CSykYVk-SUdNwlGTiD-h8Xsf2cGzniNPQNCAK6Q153BMkBc9E2AR3MjEWNU_f-15Cl2w0EIvaqGoqYrHKSMm3CIjKik_KBRTzRrbQqM5lGe_jUivjhmfwR5HOUc&secret=6191295225924896663249851881131284553005448461740837624904453538708620527945&id=bob%40alice.com') + }); + }) + + test('client can trigger promise to manage', () => { + const tokenNegotiatorClient = getOffChainConfigClient() + let client = new Client({ + type: 'active', + issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(), + options: {}, + }) + client.negotiate().then(() => { + client.handleWalletRequired([]); + }); + }) + + test('client can handle proof error', () => { + const tokenNegotiatorClient = getOffChainConfigClient() + let client = new Client({ + type: 'active', + issuers: tokenNegotiatorClient.getTokenStore().getCurrentIssuers(), + options: {}, + }) + client.negotiate().then(() => { + client.handleProofError({ error: 'something went wrong' }, 'devconVi'); + }); + }) + test('tokenNegotiatorClient a failed new instance of client - missing issuers length', () => { let client = new Client({ type: 'passive', @@ -496,121 +510,3 @@ describe('client spec', () => { }) }) - -// TODO: Reimplement cross-version test for version 3.1 -/* describe('client spec cross-version', () => { - let originalDocument = document - let originalLocation = window.location - - const nonLocalUrl = 'https://non-local.url' - - beforeAll(() => { - Object.defineProperty(global, 'document', { - value: { - location: { - href: '', - referrer: '', - hash: '', - search: '', - origin: '', - }, - addEventListener: () => { - return true - }, - }, - }) - - Object.defineProperty(window, 'location', { - value: { - href: nonLocalUrl, - origin: nonLocalUrl, - }, - writable: true, // possibility to override - }) - - // required to force redirect mode - window.navigator.brave = 1 - }) - - afterAll(() => { - Object.defineProperty(global, 'document', { - value: originalDocument, - }) - - Object.defineProperty(window, 'location', { - value: originalLocation, - }) - }) - - test('Outlet_2_0 save magicLink', async () => { - let magicLinkParams = - '?ticket=MIGTME0MATYCAgFNAgEBBEEEF6_tKK2dCfLQiwS4FuqmiQDVrafJ05vCOkYN4iT28JULCClrvI2_kGTxrL12sXlH9w9mohLQlMdmaWvFzaZVlgNCAKu7SESOLf7L5sjZPcTQVkAu9YTC88mNK8oyUjiP2gsnTUxr0BGr0eWSTYmbDqNlX3JXOEqvEH39LEQjWsXn44oc&secret=45845870684&mail=oleh.hryb.us@gmail.com' - - window.location.search = magicLinkParams - - // LocalStorage must be empty - expect(localStorage.getItem(defaultConfig.itemStorageKey)).toBe(null) - new outlet_2_0(tokenIssuer) - - expect(localStorage.getItem(defaultConfig.itemStorageKey)).toContain(magicLinkParams) - }) - - test('Redirect Client_lastest -> Outlet 2.2', async () => { - let client = new Client(config) - - // prepare Redirect URL - await client.negotiate() - let url = new URL(window.location.href) - expect(new URLSearchParams(url.hash.substring(1)).get('action')).toBe('get-issuer-tokens') - - window.location.hash = url.hash - new outlet_2_2(tokenIssuer) - - // need delay, because pageOnLoadEventHandler() is async - await delay(1000) - - let hash = new URL(document.location.href).hash.substring(1) - expect(new URLSearchParams(hash).get('action')).toBe('get-issuer-tokens-response') - }) - - test('Redirect Client_2.2 -> Outlet_lastest', async () => { - let client = new client_2_2(config) - - window.location.hash = '' - window.location.href = 'http://localhost' - document.location.hash = '' - document.location.href = 'http://localhost' - // prepare Redirect URL - await client.negotiate() - let url = new URL(document.location.href) - expect(new URLSearchParams(url.hash.substring(1)).get('action')).toBe('get-issuer-tokens') - - // console.log( - // `window.location.hash = "${window.location.hash}", - // window.location.href = "${window.location.href}", - // document.location.hash = "${document.location.hash}", - // document.location.href = "${document.location.href}",` - // ) - - window.location.hash = url.hash - document.location.hash = url.hash - document.referrer = nonLocalUrl - localStorage.setItem('tn-whitelist', '{"https://non-local.url":{"type":"read"}}') - - new Outlet(tokenIssuer) - - // need delay, because pageOnLoadEventHandler() is async - await delay(1000) - - let hash = new URL(window.location.href).hash.substring(1) - expect(new URLSearchParams(hash).get('action')).toBe('get-issuer-tokens-response') - }) - - test('tokenNegotiatorClient read prefixed param', async () => { - window.location.hash = `p1=1&${URLNS}p2=2` - let client = getOffChainConfigClient() - - expect(client.getDataFromQuery('p2')).toBe('2') - expect(client.getDataFromQuery('p1')).toBe('1') - }) -})*/