UNPKG

@mytmpvpn/mytmpvpn-client

Version:

MyTmpVpn Client Library

154 lines (153 loc) 8.3 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); const fc = __importStar(require("fast-check")); const appconfig = __importStar(require("../src/appconfig")); const src_1 = require("../src"); const location_1 = require("@mytmpvpn/mytmpvpn-common/models/location"); describe('Testing regions related APIs', () => { const appConfig = appconfig.loadDefaultAppConfig(); const client = (0, src_1.getClientModule)(appConfig.apiUrl); it("should list all locations", async () => { const locations = await client.listLocations(); expect(locations).toBeDefined(); // dev, gamma, prod all have more than 3 regions expect(Object.keys(locations).length).toBeGreaterThanOrEqual(3); locations.forEach((location) => { expect(location).toBeDefined(); expect(location.geonamesId).toBeGreaterThan(0); expect(location.city.length).toBeGreaterThan(0); expect(location.country.length).toBeGreaterThan(0); expect(location.countryCode.length).toBeGreaterThan(0); expect(location.coordinates).toBeDefined(); expect(location.coordinates.latitude).toBeDefined(); expect(location.coordinates.longitude).toBeDefined(); expect(location.providersInfo).toBeDefined(); const providersInfo = location.providersInfo; expect(providersInfo.Aws).toBeDefined(); expect(providersInfo.Aws?.infraDetails).toBeDefined(); expect(providersInfo.Aws?.infraDetails.ipv6Supported).toBeDefined(); const pricingRates = providersInfo.Aws?.pricingRates; const instanceTypes = Object.keys(pricingRates); // There should be at least one expect(instanceTypes.length).toBeGreaterThan(0); instanceTypes.forEach(instanceType => { expect(pricingRates[instanceType]).toBeDefined(); expect(pricingRates[instanceType].peanutsPerMinuteMax).toBeGreaterThan(0); expect(pricingRates[instanceType].peanutsPerMinuteMin).toBeGreaterThan(0); }); }); }); }); // --- Property-Based Test: Property 5 --- // Arbitrary: generates a valid PricingRate with non-negative values const arbPricingRate = fc.record({ peanutsPerMinuteMin: fc.double({ min: 0, max: 1000, noNaN: true, noDefaultInfinity: true }), peanutsPerMinuteMax: fc.double({ min: 0, max: 1000, noNaN: true, noDefaultInfinity: true }), }); // All valid instance types and infrastructure providers const allInstanceTypes = Object.values(location_1.InstanceType); const allProviders = Object.values(location_1.InfrastructureProvider); // Arbitrary: generates a non-empty subset of InstanceType values const arbInstanceTypeSubset = fc .subarray(allInstanceTypes, { minLength: 1 }); // Arbitrary: generates a random InfrastructureProvider const arbProvider = fc.constantFrom(...allProviders); // Arbitrary: generates a non-empty subset of providers const arbProviderSubset = fc .subarray(allProviders, { minLength: 1 }); // Arbitrary: generates a ProviderInfo with a random non-empty subset of instance types in pricingRates const arbProviderInfo = arbInstanceTypeSubset .chain((instanceTypes) => { const pricingEntries = instanceTypes.map((it) => arbPricingRate.map((rate) => [it, rate])); return fc.tuple(...pricingEntries).map((entries) => { const pricingRates = {}; for (const [it, rate] of entries) { pricingRates[it] = rate; } return pricingRates; }); }) .map((pricingRates) => ({ infraDetails: { ipv6Supported: fc.sample(fc.boolean(), 1)[0] }, pricingRates, })); // Arbitrary: generates a LocationWithProvidersInfo with random providers, each having random instance types const arbLocationWithProviders = arbProviderSubset .chain((providers) => { const providerEntries = providers.map((provider) => arbProviderInfo.map((info) => [provider, info])); return fc.tuple(...providerEntries).map((entries) => { const providersInfo = {}; for (const [provider, info] of entries) { providersInfo[provider] = info; } return providersInfo; }); }) .chain((providersInfo) => fc.tuple(fc.integer({ min: 1, max: 999999 }), fc.string({ minLength: 1, maxLength: 20 }), fc.string({ minLength: 1, maxLength: 20 }), fc.tuple(fc.constantFrom('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'), fc.constantFrom('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z')).map(([a, b]) => `${a}${b}`), fc.double({ min: -90, max: 90, noNaN: true, noDefaultInfinity: true }), fc.double({ min: -180, max: 180, noNaN: true, noDefaultInfinity: true })).map(([geonamesId, city, country, countryCode, lat, lon]) => ({ geonamesId, city, country, countryCode, coordinates: { latitude: lat, longitude: lon }, providersInfo, }))); describe('Feature: frontend-instance-type-pricing, Property 5: List-locations output contains pricing rates for all instance types', () => { /** * **Validates: Requirements 8.1, 8.2** * * For any location, each provider in providersInfo should have a pricingRates object * containing at least one InstanceType key with a valid PricingRate * (both peanutsPerMinuteMin and peanutsPerMinuteMax are non-negative numbers). */ it('should have pricingRates with at least one InstanceType key containing valid PricingRate values for each provider', () => { fc.assert(fc.property(arbLocationWithProviders, (location) => { const providers = Object.keys(location.providersInfo); // Location must have at least one provider expect(providers.length).toBeGreaterThan(0); for (const provider of providers) { const providerInfo = location.providersInfo[provider]; expect(providerInfo).toBeDefined(); const pricingRates = providerInfo.pricingRates; expect(pricingRates).toBeDefined(); const instanceTypeKeys = Object.keys(pricingRates); // Each provider must have at least one instance type in pricingRates expect(instanceTypeKeys.length).toBeGreaterThan(0); for (const instanceType of instanceTypeKeys) { // Each key must be a valid InstanceType enum value expect(allInstanceTypes).toContain(instanceType); const rate = pricingRates[instanceType]; expect(rate).toBeDefined(); // peanutsPerMinuteMin must be a non-negative number expect(typeof rate.peanutsPerMinuteMin).toBe('number'); expect(rate.peanutsPerMinuteMin).toBeGreaterThanOrEqual(0); // peanutsPerMinuteMax must be a non-negative number expect(typeof rate.peanutsPerMinuteMax).toBe('number'); expect(rate.peanutsPerMinuteMax).toBeGreaterThanOrEqual(0); } } }), { numRuns: 100 }); }); });