|
| 1 | +/* eslint-disable */ |
| 2 | + |
| 3 | +import { |
| 4 | + describe, |
| 5 | + expect, |
| 6 | + it, |
| 7 | + jest, |
| 8 | +} from '@jest/globals'; |
| 9 | +import { version as currentVersion } from '@js/core/version'; |
| 10 | + |
| 11 | +import { parseVersion } from '../../../utils/version'; |
| 12 | +import { TokenKind } from '../types'; |
| 13 | +import { parseDevExpressProductKey } from './lcp_key_validator'; |
| 14 | +import { findLatestDevExtremeVersion, isLicenseValid } from './license_info'; |
| 15 | +import { createProductInfo } from './product_info'; |
| 16 | + |
| 17 | +const DOT_NET_TICKS_EPOCH_OFFSET = 621355968000000000n; |
| 18 | +const DOT_NET_TICKS_PER_MS = 10000n; |
| 19 | +const DEVEXTREME_HTML_JS_BIT = 1n << 54n; |
| 20 | + |
| 21 | +function msToDotNetTicks(ms: number): string { |
| 22 | + return (BigInt(ms) * DOT_NET_TICKS_PER_MS + DOT_NET_TICKS_EPOCH_OFFSET).toString(); |
| 23 | +} |
| 24 | + |
| 25 | +function createLcpSource(payload: string): string { |
| 26 | + const signature = 'A'.repeat(136); |
| 27 | + return `LCPv1${btoa(`${signature}${payload}`)}`; |
| 28 | +} |
| 29 | + |
| 30 | +function loadParserWithBypassedSignatureCheck() { |
| 31 | + jest.resetModules(); |
| 32 | + jest.doMock('./utils', () => { |
| 33 | + const actual = jest.requireActual('./utils') as Record<string, unknown>; |
| 34 | + return { |
| 35 | + ...actual, |
| 36 | + encodeString: (text: string) => text, |
| 37 | + shiftDecodeText: (text: string) => text, |
| 38 | + verifyHash: () => true, |
| 39 | + }; |
| 40 | + }); |
| 41 | + |
| 42 | + // eslint-disable-next-line |
| 43 | + const { parseDevExpressProductKey } = require('./lcp_key_validator'); |
| 44 | + // eslint-disable-next-line |
| 45 | + const { TokenKind } = require('../types'); |
| 46 | + return { parseDevExpressProductKey, TokenKind }; |
| 47 | +} |
| 48 | + |
| 49 | +function getTrialLicense() { |
| 50 | + const { major, minor } = parseVersion(currentVersion); |
| 51 | + const products = [ |
| 52 | + createProductInfo(parseInt(`${major}${minor}`, 10), 0n), |
| 53 | + ]; |
| 54 | + return { products }; |
| 55 | +} |
| 56 | + |
| 57 | +describe('LCP key validation', () => { |
| 58 | + it('serializer returns an invalid license for malformed input', () => { |
| 59 | + const token = parseDevExpressProductKey('not-a-real-license'); |
| 60 | + expect(token.kind).toBe(TokenKind.corrupted); |
| 61 | + }); |
| 62 | + |
| 63 | + (process.env.DX_PRODUCT_KEY ? it : it.skip)('developer product license fixtures parse into valid LicenseInfo instances', () => { |
| 64 | + const token = parseDevExpressProductKey(process.env.DX_PRODUCT_KEY as string); |
| 65 | + expect(token.kind).toBe(TokenKind.verified); |
| 66 | + }); |
| 67 | + |
| 68 | + it('trial fallback does not grant product access', () => { |
| 69 | + const trialLicense = getTrialLicense(); |
| 70 | + expect(isLicenseValid(trialLicense)).toBe(true); |
| 71 | + |
| 72 | + const version = findLatestDevExtremeVersion(trialLicense); |
| 73 | + |
| 74 | + expect(version).toBe(undefined); |
| 75 | + }); |
| 76 | + |
| 77 | + it('does not classify a valid DevExtreme product key as trial-expired when expiration metadata is in the past', () => { |
| 78 | + const { parseDevExpressProductKey, TokenKind } = loadParserWithBypassedSignatureCheck(); |
| 79 | + const expiredAt = msToDotNetTicks(Date.UTC(2020, 0, 1)); |
| 80 | + |
| 81 | + const payload = `meta;251,${DEVEXTREME_HTML_JS_BIT},0,${expiredAt};`; |
| 82 | + const token = parseDevExpressProductKey(createLcpSource(payload)); |
| 83 | + |
| 84 | + expect(token.kind).toBe(TokenKind.verified); |
| 85 | + }); |
| 86 | + |
| 87 | + it('returns trial-expired for expired trial keys without DevExtreme product access', () => { |
| 88 | + const { parseDevExpressProductKey, TokenKind } = loadParserWithBypassedSignatureCheck(); |
| 89 | + const expiredAt = msToDotNetTicks(Date.UTC(2020, 0, 1)); |
| 90 | + |
| 91 | + const payload = `meta;251,0,0,${expiredAt};`; |
| 92 | + const token = parseDevExpressProductKey(createLcpSource(payload)); |
| 93 | + |
| 94 | + expect(token.kind).toBe(TokenKind.corrupted); |
| 95 | + if (token.kind === TokenKind.corrupted) { |
| 96 | + expect(token.error).toBe('trial-expired'); |
| 97 | + } |
| 98 | + }); |
| 99 | +}); |
0 commit comments