diff --git a/js/tweek-client/package.json b/js/tweek-client/package.json index 9aa533fd..6efd4092 100644 --- a/js/tweek-client/package.json +++ b/js/tweek-client/package.json @@ -1,6 +1,6 @@ { "name": "tweek-client", - "version": "1.0.0", + "version": "1.0.0-rc7", "description": "Tweek client for JavaScript", "author": "Soluto", "license": "MIT", diff --git a/js/tweek-client/src/TweekClient/KeyValuesError.ts b/js/tweek-client/src/TweekClient/KeyValuesError.ts deleted file mode 100644 index 777efbbe..00000000 --- a/js/tweek-client/src/TweekClient/KeyValuesError.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { KeyValuesErrors } from './types'; - -export class KeyValuesError extends Error { - constructor(keyValuesErrors: KeyValuesErrors, message: string); - constructor(public keyValuesErrors: KeyValuesErrors, ...args: any[]) { - super(...args); - - Object.setPrototypeOf(this, KeyValuesError.prototype); - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, KeyValuesError); - } - } -} diff --git a/js/tweek-client/src/TweekClient/TweekClient.ts b/js/tweek-client/src/TweekClient/TweekClient.ts index 3b1b8d79..f4d23e10 100644 --- a/js/tweek-client/src/TweekClient/TweekClient.ts +++ b/js/tweek-client/src/TweekClient/TweekClient.ts @@ -1,38 +1,9 @@ import { InputParams } from 'query-string'; import chunk from 'lodash.chunk'; -import { deprecated, normalizeBaseUrl, optimizeInclude, toQueryString } from '../utils'; +import { normalizeBaseUrl, optimizeInclude, toQueryString } from '../utils'; import { TweekInitConfig } from '../types'; import { FetchError } from '../FetchError'; -import { - Context, - GetValuesConfig, - ITweekClient, - KeyValuesErrorHandler, - KeyValuesErrors, - TweekClientConfig, -} from './types'; -import { KeyValuesError } from './KeyValuesError'; - -type TweekResult = { - data: T; - errors: KeyValuesErrors; -}; - -function extractData( - { data, errors }: TweekResult, - throwOnError: boolean | undefined, - onKeyValueError: KeyValuesErrorHandler | undefined, -) { - if (errors && Object.keys(errors).length > 0) { - if (onKeyValueError) { - Object.entries(errors as KeyValuesErrors).forEach(([k, e]) => onKeyValueError(k, e)); - } - if (throwOnError) { - throw new KeyValuesError(errors, 'Tweek values had errors'); - } - } - return data; -} +import { Context, GetValuesConfig, ITweekClient, TweekClientConfig } from './types'; export default class TweekClient implements ITweekClient { config: TweekClientConfig; @@ -54,37 +25,26 @@ export default class TweekClient implements ITweekClient { ..._config, }; - const { include, maxChunkSize = 100, throwOnError, onKeyValueError } = cfg; + const { include, maxChunkSize = 100 } = cfg; if (!include) { - return this._fetchChunk(path, cfg).then(res => extractData(res, throwOnError, onKeyValueError)); + return this._fetchChunk(path, cfg); } const optimizedInclude = optimizeInclude(include); const includeChunks = chunk(optimizedInclude, maxChunkSize); const fetchConfigChunks = includeChunks.map(ic => ({ ...cfg, include: ic })); - const fetchPromises = fetchConfigChunks.map(cc => this._fetchChunk(path, cc)); - return Promise.all(fetchPromises).then(chunks => { - const res = chunks.reduce((res, ch) => ({ - data: { ...res.data, ...ch.data }, - errors: { ...res.errors, ...ch.errors }, - })); - return extractData(res, throwOnError, onKeyValueError); - }); + const fetchPromises = fetchConfigChunks.map(cc => this._fetchChunk(path, cc)); + return >Promise.all(fetchPromises).then(chunks => chunks.reduce((res, ch) => ({ ...res, ...ch }), {})); } - @deprecated('getValues') - fetch(path: string, config?: GetValuesConfig): Promise { - return this.getValues(path, config); - } + fetch = this.getValues; - private _fetchChunk(path: string, _config: TweekInitConfig & GetValuesConfig): Promise> { + private _fetchChunk(path: string, _config: TweekInitConfig & GetValuesConfig): Promise { const { flatten, baseServiceUrl, context, include, ignoreKeyTypes } = _config; const queryParamsObject = this._contextToQueryParams(context); - queryParamsObject['$includeErrors'] = true; - if (flatten) { queryParamsObject['$flatten'] = true; } diff --git a/js/tweek-client/src/TweekClient/TweekClientWithFallback.ts b/js/tweek-client/src/TweekClient/TweekClientWithFallback.ts deleted file mode 100644 index 4dd91b54..00000000 --- a/js/tweek-client/src/TweekClient/TweekClientWithFallback.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { GetValuesConfig, ITweekClient } from './types'; - -export default class TweekClientWithFallback implements ITweekClient { - constructor(private readonly _clients: ITweekClient[]) {} - - getValues(path: string, config: GetValuesConfig): Promise { - return this._execute(client => client.getValues(path, config)); - } - - fetch(path: string, config?: GetValuesConfig): Promise { - return this._execute(client => client.fetch(path, config)); - } - - private _execute(fn: (client: ITweekClient) => Promise): Promise { - return this._clients.reduce((acc, client) => acc.catch(() => fn(client)), Promise.reject( - new Error('TweekClientWithFallback has no clients'), - ) as Promise); - } -} diff --git a/js/tweek-client/src/TweekClient/createTweekClient.ts b/js/tweek-client/src/TweekClient/createTweekClient.ts index 89028327..ae0c6e7d 100644 --- a/js/tweek-client/src/TweekClient/createTweekClient.ts +++ b/js/tweek-client/src/TweekClient/createTweekClient.ts @@ -1,9 +1,11 @@ import { createFetchClient } from '../utils'; -import { BaseCreateTweekClientConfig } from './types'; +import { CreateClientConfig } from '../types'; +import { Context } from './types'; import TweekClient from './TweekClient'; -export type CreateTweekClientConfig = BaseCreateTweekClientConfig & { - baseServiceUrl: string; +export type CreateTweekClientConfig = CreateClientConfig & { + context?: Context; + useLegacyEndpoint?: boolean; }; export function createTweekClient({ diff --git a/js/tweek-client/src/TweekClient/createTweekClientWithFallback.ts b/js/tweek-client/src/TweekClient/createTweekClientWithFallback.ts deleted file mode 100644 index bbb8f416..00000000 --- a/js/tweek-client/src/TweekClient/createTweekClientWithFallback.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createTweekClient } from './createTweekClient'; -import TweekClientWithFallback from './TweekClientWithFallback'; -import { BaseCreateTweekClientConfig } from './types'; - -export type CreateTweekClientConfigWithFallback = BaseCreateTweekClientConfig & { - urls: string[]; -}; - -export function createTweekClientWithFallback({ urls, ...config }: CreateTweekClientConfigWithFallback) { - const clients = urls.map(baseServiceUrl => createTweekClient({ baseServiceUrl, ...config })); - return new TweekClientWithFallback(clients); -} diff --git a/js/tweek-client/src/TweekClient/index.ts b/js/tweek-client/src/TweekClient/index.ts index de794314..a216cbe1 100644 --- a/js/tweek-client/src/TweekClient/index.ts +++ b/js/tweek-client/src/TweekClient/index.ts @@ -1,6 +1,3 @@ export * from './types'; export { default as TweekClient } from './TweekClient'; -export { default as TweekClientWithFallback } from './TweekClientWithFallback'; export * from './createTweekClient'; -export * from './createTweekClientWithFallback'; -export * from './KeyValuesError'; diff --git a/js/tweek-client/src/TweekClient/types.ts b/js/tweek-client/src/TweekClient/types.ts index fd0a52c9..fa7c3d1b 100644 --- a/js/tweek-client/src/TweekClient/types.ts +++ b/js/tweek-client/src/TweekClient/types.ts @@ -1,4 +1,4 @@ -import { FetchClientConfig, IdentityContext, TweekInitConfig } from '../types'; +import { IdentityContext, TweekInitConfig } from '../types'; export type Context = { [identityType: string]: string | ({ id?: string } & IdentityContext); @@ -8,28 +8,17 @@ type RequestConfig = { include?: string[]; }; -export type KeyValuesErrors = { [keyPath: string]: string }; - -export type KeyValuesErrorHandler = (keyPath: string, error: string) => void; - type ClientConfig = { context?: Context; flatten?: boolean; ignoreKeyTypes?: boolean; maxChunkSize?: number; - onKeyValueError?: KeyValuesErrorHandler; - throwOnError?: boolean; }; export type GetValuesConfig = ClientConfig & RequestConfig; export type TweekClientConfig = TweekInitConfig & ClientConfig; -export type BaseCreateTweekClientConfig = FetchClientConfig & { - context?: Context; - useLegacyEndpoint?: boolean; -}; - export interface ITweekClient { getValues(path: string, config?: GetValuesConfig): Promise; diff --git a/js/tweek-client/src/TweekManagementClient/createTweekManagementClient.ts b/js/tweek-client/src/TweekManagementClient/createTweekManagementClient.ts index 7936871f..ee6d4da1 100644 --- a/js/tweek-client/src/TweekManagementClient/createTweekManagementClient.ts +++ b/js/tweek-client/src/TweekManagementClient/createTweekManagementClient.ts @@ -1,15 +1,8 @@ import { createFetchClient } from '../utils'; -import { FetchClientConfig } from '../types'; +import { CreateClientConfig } from '../types'; import TweekManagementClient from './TweekManagementClient'; -export type CreateTweekManagementClientConfig = FetchClientConfig & { - baseServiceUrl: string; -}; - -export function createTweekManagementClient({ - baseServiceUrl, - ...fetchClientConfig -}: CreateTweekManagementClientConfig) { +export function createTweekManagementClient({ baseServiceUrl, ...fetchClientConfig }: CreateClientConfig) { return new TweekManagementClient({ baseServiceUrl, fetch: createFetchClient(fetchClientConfig), diff --git a/js/tweek-client/src/types.ts b/js/tweek-client/src/types.ts index 83b93011..bbd15b06 100644 --- a/js/tweek-client/src/types.ts +++ b/js/tweek-client/src/types.ts @@ -30,3 +30,7 @@ export type FetchClientConfig = (BearerAuthenticationOptions | ClientCredentials requestTimeoutInMillis?: number; onError?(response: Response): void; }; + +export type CreateClientConfig = FetchClientConfig & { + baseServiceUrl: string; +}; diff --git a/js/tweek-client/src/utils.ts b/js/tweek-client/src/utils.ts index d2f00bd6..5088e665 100644 --- a/js/tweek-client/src/utils.ts +++ b/js/tweek-client/src/utils.ts @@ -141,21 +141,3 @@ export const toQueryString = (query: InputParams) => { const queryString = qs.stringify(query); return queryString ? `?${queryString}` : ''; }; - -export function deprecated(newMethod: string) { - let notified = false; - return function(target: Object, propertyKey: string, descriptor: PropertyDescriptor) { - const originalValue = descriptor.value; - descriptor.value = function() { - if (!notified) { - if (typeof process !== 'undefined' && process.env.NODE_ENV !== 'production') { - const name = target.constructor.name; - console.warn(`the ${name}.${propertyKey} method is deprecated, please use ${name}.${newMethod} instead`); - } - notified = true; - } - - return originalValue.apply(this, arguments); - }; - }; -} diff --git a/js/tweek-client/test/TweekClient/errorHandling.spec.ts b/js/tweek-client/test/TweekClient/errorHandling.spec.ts deleted file mode 100644 index 1fac760e..00000000 --- a/js/tweek-client/test/TweekClient/errorHandling.spec.ts +++ /dev/null @@ -1,100 +0,0 @@ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { KeyValuesError, TweekClient } from '../../src'; - -describe('TweekClient errorHandling', () => { - let fetchStub: sinon.SinonStub; - let onKeyError: sinon.SinonStub; - let tweekClient: TweekClient; - - beforeEach(() => { - fetchStub = sinon.stub(); - onKeyError = sinon.stub(); - }); - - describe('onKeyValueError', () => { - beforeEach(() => { - tweekClient = new TweekClient({ - baseServiceUrl: '', - fetch: fetchStub, - onKeyValueError: onKeyError, - }); - }); - - it('should not call onKeyValueError if errors is not in the response body', async () => { - fetchStub.resolves(new Response(JSON.stringify({}))); - - await tweekClient.getValues(''); - - sinon.assert.notCalled(onKeyError); - }); - - it('should not call onKeyValueError if errors object is empty', async () => { - fetchStub.resolves(new Response(JSON.stringify({ errors: {} }))); - - await tweekClient.getValues(''); - - sinon.assert.notCalled(onKeyError); - }); - - it('should call onKeyValueError if errors object contains errors', async () => { - const errors = { - some_key: 'some error', - other_key: 'other error', - }; - fetchStub.resolves(new Response(JSON.stringify({ errors }))); - - await tweekClient.getValues(''); - - Object.entries(errors).forEach(([keyPath, error]) => sinon.assert.calledWithExactly(onKeyError, keyPath, error)); - }); - }); - - describe('throwOnError', () => { - beforeEach(() => { - tweekClient = new TweekClient({ - baseServiceUrl: '', - fetch: fetchStub, - throwOnError: true, - }); - }); - - it('should not throw if errors is not in the response body', async () => { - fetchStub.resolves(new Response(JSON.stringify({}))); - - await tweekClient.getValues(''); - }); - - it('should not throw if errors object is empty', async () => { - fetchStub.resolves(new Response(JSON.stringify({ errors: {} }))); - - await tweekClient.getValues(''); - }); - - it('should throw if errors object contains errors', async () => { - const errors = { some_key: 'some error' }; - fetchStub.resolves(new Response(JSON.stringify({ errors }))); - - await expect(tweekClient.getValues('')).to.be.rejectedWith(KeyValuesError); - }); - }); - - it('should throw and call onKeyValueError if both are defined', async () => { - const keyPath = 'some_key'; - const error = 'some error'; - - tweekClient = new TweekClient({ - baseServiceUrl: '', - fetch: fetchStub, - onKeyValueError: onKeyError, - throwOnError: true, - }); - - fetchStub.resolves(new Response(JSON.stringify({ errors: { [keyPath]: error } }))); - - await expect(tweekClient.getValues('')).to.be.rejectedWith(KeyValuesError); - - sinon.assert.calledOnce(onKeyError); - sinon.assert.calledWithExactly(onKeyError, keyPath, error); - }); -}); diff --git a/js/tweek-client/test/TweekClient/fetchChuncks.spec.ts b/js/tweek-client/test/TweekClient/fetchChuncks.spec.ts index 3edcbf67..16e637d1 100644 --- a/js/tweek-client/test/TweekClient/fetchChuncks.spec.ts +++ b/js/tweek-client/test/TweekClient/fetchChuncks.spec.ts @@ -29,16 +29,16 @@ describe('TweekClient fetchChunks', () => { expectedUrl: `${defaultUrl}api/v2/values/_`, stubCalls: [ { - requestUrl: 'http://test/api/v2/values/_?%24include=a1&%24include=a2&%24include=a3&%24includeErrors=true', - response: new Response('{"data": { "a1": 1, "a2": 2, "a3": 3 } }'), + requestUrl: 'http://test/api/v2/values/_?%24include=a1&%24include=a2&%24include=a3', + response: new Response('{ "a1": 1, "a2": 2, "a3": 3 }'), }, { - requestUrl: 'http://test/api/v2/values/_?%24include=b1&%24include=b2&%24include=b3&%24includeErrors=true', - response: new Response('{ "data": { "b1": "a", "b2": "b", "b3": "c" } }'), + requestUrl: 'http://test/api/v2/values/_?%24include=b1&%24include=b2&%24include=b3', + response: new Response('{ "b1": "a", "b2": "b", "b3": "c" }'), }, { - requestUrl: 'http://test/api/v2/values/_?%24include=c5&%24includeErrors=true', - response: new Response('{ "data": { "c5": true } }'), + requestUrl: 'http://test/api/v2/values/_?%24include=c5', + response: new Response('{ "c5": true }'), }, ], config: { diff --git a/js/tweek-client/test/TweekClient/getValues.spec.ts b/js/tweek-client/test/TweekClient/getValues.spec.ts index a42b2ae0..9b537f9a 100644 --- a/js/tweek-client/test/TweekClient/getValues.spec.ts +++ b/js/tweek-client/test/TweekClient/getValues.spec.ts @@ -1,12 +1,12 @@ import sinon from 'sinon'; import { expect } from 'chai'; -import qs, { InputParams } from 'query-string'; import { GetValuesConfig, TweekClient } from '../../src'; -export const toQueryString = (query: InputParams | undefined) => { - const queryString = qs.stringify({ $includeErrors: true, ...query }); - return queryString ? `?${queryString}` : ''; -}; +const ENCODE_$_CHARACTER = encodeURIComponent('$'); +const ENCODE_SLASH_CHARACTER = encodeURIComponent('/'); + +const queryParamsEncoder = (queryParams: string) => + queryParams.replace(/\$/g, ENCODE_$_CHARACTER).replace(/\//g, ENCODE_SLASH_CHARACTER); describe('TweekClient getValues', () => { const defaultUrl = 'http://test/'; @@ -29,7 +29,7 @@ describe('TweekClient getValues', () => { const testsDefenitions: { pathToFetch: string; - expectedQueryParams?: InputParams; + expectedQueryParams?: string; resultsToResolve?: any; config?: GetValuesConfig; expectedResult?: any; @@ -45,7 +45,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $include: 'abc' }, + expectedQueryParams: `?$include=abc`, config: { include: ['abc'], }, @@ -53,7 +53,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $include: ['path1', 'path2/key', 'path3/_'] }, + expectedQueryParams: `?$include=path1&$include=path2/key&$include=path3/_`, config: { include: ['path1', 'path2/key', 'path3/_'], }, @@ -61,7 +61,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { user: 'userid', 'user.gender': 'male' }, + expectedQueryParams: `?user=userid&user.gender=male`, config: { context: { user: { @@ -74,7 +74,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { user: 'userid' }, + expectedQueryParams: `?user=userid`, config: { context: { user: 'userid', @@ -90,7 +90,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $flatten: true }, + expectedQueryParams: `?$flatten=true`, config: { flatten: true }, resultsToResolve: { 'some_path/some_key': true }, expectedResult: { 'some_path/some_key': true }, @@ -98,7 +98,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $flatten: true }, + expectedQueryParams: `?$flatten=true`, config: { flatten: true }, resultsToResolve: { 'some_path/some_key': 'true' }, expectedResult: { 'some_path/some_key': 'true' }, @@ -106,7 +106,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $flatten: true }, + expectedQueryParams: `?$flatten=true`, config: { flatten: true }, resultsToResolve: { 'some_path/some_key': 'true' }, expectedResult: { 'some_path/some_key': 'true' }, @@ -115,7 +115,7 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $flatten: true, $ignoreKeyTypes: true }, + expectedQueryParams: `?$flatten=true&$ignoreKeyTypes=true`, config: { flatten: true, ignoreKeyTypes: true }, resultsToResolve: { 'some_path/some_key': 'true' }, expectedResult: { 'some_path/some_key': 'true' }, @@ -123,19 +123,19 @@ describe('TweekClient getValues', () => { testsDefenitions.push({ pathToFetch: '_', - expectedQueryParams: { $flatten: true }, + expectedQueryParams: `?$flatten=true`, config: { flatten: true, ignoreKeyTypes: false }, resultsToResolve: { 'some_path/some_key': true }, expectedResult: { 'some_path/some_key': true }, }); testsDefenitions.forEach( - ({ baseUrl, pathToFetch, config, resultsToResolve = {}, expectedQueryParams, expectedResult }) => + ({ baseUrl, pathToFetch, config, resultsToResolve = {}, expectedQueryParams = '', expectedResult }) => it('should execute getValues correctly', async () => { // Arrange const { tweekClient, fetchStub } = prepare(baseUrl); - fetchStub.resolves(new Response(JSON.stringify({ data: resultsToResolve }))); - const expectedUrl = `${defaultUrl}api/v2/values/${pathToFetch}` + toQueryString(expectedQueryParams); + fetchStub.resolves(new Response(JSON.stringify(resultsToResolve))); + const expectedUrl = `${defaultUrl}api/v2/values/${pathToFetch}` + queryParamsEncoder(expectedQueryParams); // Act const result = await tweekClient.getValues(pathToFetch, config); @@ -158,6 +158,6 @@ describe('TweekClient getValues', () => { // Assert sinon.assert.calledOnce(fetchStub); - sinon.assert.calledWithExactly(fetchStub, `${defaultUrl}api/v1/keys/_${toQueryString(undefined)}`); + sinon.assert.calledWithExactly(fetchStub, `${defaultUrl}api/v1/keys/_`); }); }); diff --git a/js/tweek-client/test/TweekClientWithFallback.spec.ts b/js/tweek-client/test/TweekClientWithFallback.spec.ts deleted file mode 100644 index 1f9eaa8e..00000000 --- a/js/tweek-client/test/TweekClientWithFallback.spec.ts +++ /dev/null @@ -1,125 +0,0 @@ -import sinon from 'sinon'; -import { expect } from 'chai'; -import { TweekClientWithFallback } from '../src'; - -function createStub(shouldFail: boolean) { - const stub = sinon.stub(); - if (shouldFail) { - stub.rejects(); - } else { - stub.resolves(); - } - return stub; -} - -function createMockClient(shouldFail = false) { - return { - getValues: createStub(shouldFail), - fetch: createStub(shouldFail), - }; -} - -describe('TweekClientWithFallback', () => { - const path = 'somePath'; - const config = {}; - - describe('getValues', () => { - function assertCalled(client: any) { - sinon.assert.calledOnce(client.getValues); - sinon.assert.calledWithExactly(client.getValues, path, config); - } - - function assertNotCalled(client: any) { - sinon.assert.notCalled(client.getValues); - } - - it('should fail if no clients are passed', async () => { - const tweekClient = new TweekClientWithFallback([]); - - await expect(tweekClient.getValues(path, config)).to.be.rejected; - }); - - it('should stop calling clients after client succeeds', async () => { - const clients = [createMockClient(), createMockClient(true), createMockClient(true)]; - const tweekClient = new TweekClientWithFallback(clients as any); - - await tweekClient.getValues(path, config); - - assertCalled(clients[0]); - assertNotCalled(clients[1]); - assertNotCalled(clients[2]); - }); - - it('should stop calling clients after client succeeds', async () => { - const clients = [createMockClient(true), createMockClient(), createMockClient(true)]; - const tweekClient = new TweekClientWithFallback(clients as any); - - await tweekClient.getValues(path, config); - - assertCalled(clients[0]); - assertCalled(clients[1]); - assertNotCalled(clients[2]); - }); - - it('should fail if all clients fail', async () => { - const clients = [createMockClient(true), createMockClient(true), createMockClient(true)]; - const tweekClient = new TweekClientWithFallback(clients as any); - - await expect(tweekClient.getValues(path, config)).to.be.rejected; - - assertCalled(clients[0]); - assertCalled(clients[1]); - assertCalled(clients[2]); - }); - }); - - describe('fetch', () => { - function assertCalled(client: any) { - sinon.assert.calledOnce(client.fetch); - sinon.assert.calledWithExactly(client.fetch, path, config); - } - - function assertNotCalled(client: any) { - sinon.assert.notCalled(client.fetch); - } - - it('should fail if no clients are passed', async () => { - const tweekClient = new TweekClientWithFallback([]); - - await expect(tweekClient.fetch(path, config)).to.be.rejected; - }); - - it('should stop calling clients after client succeeds', async () => { - const clients = [createMockClient(), createMockClient(true), createMockClient(true)]; - const tweekClient = new TweekClientWithFallback(clients as any); - - await tweekClient.fetch(path, config); - - assertCalled(clients[0]); - assertNotCalled(clients[1]); - assertNotCalled(clients[2]); - }); - - it('should stop calling clients after client succeeds', async () => { - const clients = [createMockClient(true), createMockClient(), createMockClient(true)]; - const tweekClient = new TweekClientWithFallback(clients as any); - - await tweekClient.fetch(path, config); - - assertCalled(clients[0]); - assertCalled(clients[1]); - assertNotCalled(clients[2]); - }); - - it('should fail if all clients fail', async () => { - const clients = [createMockClient(true), createMockClient(true), createMockClient(true)]; - const tweekClient = new TweekClientWithFallback(clients as any); - - await expect(tweekClient.fetch(path, config)).to.be.rejected; - - assertCalled(clients[0]); - assertCalled(clients[1]); - assertCalled(clients[2]); - }); - }); -}); diff --git a/js/tweek-client/test/createTweekClient.spec.ts b/js/tweek-client/test/createTweekClient.spec.ts index 32bdd466..a1aaf4e5 100644 --- a/js/tweek-client/test/createTweekClient.spec.ts +++ b/js/tweek-client/test/createTweekClient.spec.ts @@ -17,7 +17,7 @@ describe('createTweekClient', () => { beforeEach(() => { fetchMock.getOnce( '*', - { data: {} }, + {}, { name: matcherName, }, @@ -90,7 +90,9 @@ describe('createTweekClient', () => { it('should return arrays correctly', async () => { const expectedResult = [1, 2, 3]; fetchMock.restore(); - fetchMock.getOnce('*', { data: expectedResult }, { name: matcherName }); + fetchMock.getOnce('*', expectedResult, { + name: matcherName, + }); const tweekClient = createTweekClient({ baseServiceUrl, diff --git a/js/tweek-local-cache/package.json b/js/tweek-local-cache/package.json index 961646cc..248b7a48 100644 --- a/js/tweek-local-cache/package.json +++ b/js/tweek-local-cache/package.json @@ -35,7 +35,7 @@ "simple-fake-server": "^2.2.0", "sinon": "^7.2.3", "ts-node": "^8.0.2", - "tweek-client": "^1.0.0", + "tweek-client": "^1.0.0-rc5", "typescript": "^3.3.1", "wait-port": "^0.2.2" }, diff --git a/js/tweek-local-cache/spec/unit/tweek-repository.spec.ts b/js/tweek-local-cache/spec/unit/tweek-repository.spec.ts index 41479181..e74b8f6f 100644 --- a/js/tweek-local-cache/spec/unit/tweek-repository.spec.ts +++ b/js/tweek-local-cache/spec/unit/tweek-repository.spec.ts @@ -69,16 +69,14 @@ describe('tweek repo test', () => { .get() .to('/api/v2/values/_/*') .willReturn({ - data: { - 'my_path/string_value': 'my-string', - 'my_path/inner_path_1/int_value': 55, - 'my_path/inner_path_1/bool_positive_value': true, - 'my_path/inner_path_2/bool_negative_value': false, - 'some_path/inner_path_1/first_value': 'value_1', - 'some_path/inner_path_1/second_value': 'value_2', - 'deeply_nested/a/b/c/d/value': 'value_5', - 'some_other_path/inner_path_2/third_value': 'value_3', - }, + 'my_path/string_value': 'my-string', + 'my_path/inner_path_1/int_value': 55, + 'my_path/inner_path_1/bool_positive_value': true, + 'my_path/inner_path_2/bool_negative_value': false, + 'some_path/inner_path_1/first_value': 'value_1', + 'some_path/inner_path_1/second_value': 'value_2', + 'deeply_nested/a/b/c/d/value': 'value_5', + 'some_other_path/inner_path_2/third_value': 'value_3', }); _createClientThatFails = () => { diff --git a/js/tweek-local-cache/tsconfig.json b/js/tweek-local-cache/tsconfig.json index 8904bf15..9b1a8ff4 100644 --- a/js/tweek-local-cache/tsconfig.json +++ b/js/tweek-local-cache/tsconfig.json @@ -1,6 +1,7 @@ { "extends": "../../tsconfig", "compilerOptions": { + "experimentalDecorators": true, /* Basic Options */ "lib": ["dom", "esnext"], "outDir": "./dist" diff --git a/tsconfig.json b/tsconfig.json index 3cf50aba..59f7f7b5 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -24,7 +24,6 @@ "noFallthroughCasesInSwitch": true, /* Module Resolution Options */ - "experimentalDecorators": true, "esModuleInterop": true } }