@servicetitan/launchdarkly-service 31.0.0 → 31.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/tests/feature-flag-provider.test.d.ts +2 -0
- package/dist/tests/feature-flag-provider.test.d.ts.map +1 -0
- package/dist/tests/feature-flag-provider.test.js +46 -0
- package/dist/tests/feature-flag-provider.test.js.map +1 -0
- package/dist/tests/feature-flag-store.test.d.ts +2 -0
- package/dist/tests/feature-flag-store.test.d.ts.map +1 -0
- package/dist/tests/feature-flag-store.test.js +32 -0
- package/dist/tests/feature-flag-store.test.js.map +1 -0
- package/dist/tests/get-ld-client.test.d.ts +2 -0
- package/dist/tests/get-ld-client.test.d.ts.map +1 -0
- package/dist/tests/get-ld-client.test.js +61 -0
- package/dist/tests/get-ld-client.test.js.map +1 -0
- package/dist/tests/ld-provider.test.d.ts +2 -0
- package/dist/tests/ld-provider.test.d.ts.map +1 -0
- package/dist/tests/ld-provider.test.js +182 -0
- package/dist/tests/ld-provider.test.js.map +1 -0
- package/dist/tests/ld-service-provider.test.d.ts +2 -0
- package/dist/tests/ld-service-provider.test.d.ts.map +1 -0
- package/dist/tests/ld-service-provider.test.js +42 -0
- package/dist/tests/ld-service-provider.test.js.map +1 -0
- package/dist/tests/with-feature-flag.test.d.ts +2 -0
- package/dist/tests/with-feature-flag.test.d.ts.map +1 -0
- package/dist/tests/with-feature-flag.test.js +73 -0
- package/dist/tests/with-feature-flag.test.js.map +1 -0
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-flag-provider.test.d.ts","sourceRoot":"","sources":["../../src/tests/feature-flag-provider.test.tsx"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { Provider } from '@servicetitan/react-ioc';
|
|
4
|
+
import { render, screen } from '@testing-library/react';
|
|
5
|
+
import { FeatureFlagProvider } from '../feature-flag-provider';
|
|
6
|
+
import { FeatureFlagStore } from '../feature-flag-store';
|
|
7
|
+
import { useFlags } from 'launchdarkly-react-client-sdk';
|
|
8
|
+
jest.mock('launchdarkly-react-client-sdk', ()=>({
|
|
9
|
+
useFlags: jest.fn()
|
|
10
|
+
}));
|
|
11
|
+
describe(`[launchdarkly-service] ${FeatureFlagProvider.name}`, ()=>{
|
|
12
|
+
const flags = {
|
|
13
|
+
foo: 'bar',
|
|
14
|
+
baz: 'qux'
|
|
15
|
+
};
|
|
16
|
+
const mockFeatureFlagStore = {
|
|
17
|
+
setFlags: jest.fn()
|
|
18
|
+
};
|
|
19
|
+
const Component = ()=>{
|
|
20
|
+
return `<Component />`;
|
|
21
|
+
};
|
|
22
|
+
beforeEach(()=>{
|
|
23
|
+
jest.mocked(useFlags).mockImplementation(()=>flags);
|
|
24
|
+
});
|
|
25
|
+
const subject = ()=>render(/*#__PURE__*/ _jsx(Provider, {
|
|
26
|
+
singletons: [
|
|
27
|
+
{
|
|
28
|
+
provide: FeatureFlagStore,
|
|
29
|
+
useValue: mockFeatureFlagStore
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
children: /*#__PURE__*/ _jsx(FeatureFlagProvider, {
|
|
33
|
+
children: /*#__PURE__*/ _jsx(Component, {})
|
|
34
|
+
})
|
|
35
|
+
}));
|
|
36
|
+
test('renders children', ()=>{
|
|
37
|
+
subject();
|
|
38
|
+
expect(screen.getByText(`<Component />`)).toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
test('sets feature flags in store', ()=>{
|
|
41
|
+
subject();
|
|
42
|
+
expect(mockFeatureFlagStore.setFlags).toHaveBeenCalledWith(flags);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
//# sourceMappingURL=feature-flag-provider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tests/feature-flag-provider.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { Provider } from '@servicetitan/react-ioc';\nimport { FC } from 'react';\nimport { render, screen } from '@testing-library/react';\n\nimport { FeatureFlagProvider } from '../feature-flag-provider';\nimport { FeatureFlagStore } from '../feature-flag-store';\nimport { useFlags } from 'launchdarkly-react-client-sdk';\n\njest.mock('launchdarkly-react-client-sdk', () => ({\n useFlags: jest.fn(),\n}));\n\ndescribe(`[launchdarkly-service] ${FeatureFlagProvider.name}`, () => {\n const flags = { foo: 'bar', baz: 'qux' };\n const mockFeatureFlagStore = {\n setFlags: jest.fn(),\n };\n\n const Component: FC = () => {\n return `<Component />`;\n };\n\n beforeEach(() => {\n jest.mocked(useFlags).mockImplementation(() => flags);\n });\n\n const subject = () =>\n render(\n <Provider singletons={[{ provide: FeatureFlagStore, useValue: mockFeatureFlagStore }]}>\n <FeatureFlagProvider>\n <Component />\n </FeatureFlagProvider>\n </Provider>\n );\n\n test('renders children', () => {\n subject();\n\n expect(screen.getByText(`<Component />`)).toBeInTheDocument();\n });\n\n test('sets feature flags in store', () => {\n subject();\n\n expect(mockFeatureFlagStore.setFlags).toHaveBeenCalledWith(flags);\n });\n});\n"],"names":["Provider","render","screen","FeatureFlagProvider","FeatureFlagStore","useFlags","jest","mock","fn","describe","name","flags","foo","baz","mockFeatureFlagStore","setFlags","Component","beforeEach","mocked","mockImplementation","subject","singletons","provide","useValue","test","expect","getByText","toBeInTheDocument","toHaveBeenCalledWith"],"mappings":";AAAA,OAAO,4BAA4B;AACnC,SAASA,QAAQ,QAAQ,0BAA0B;AAEnD,SAASC,MAAM,EAAEC,MAAM,QAAQ,yBAAyB;AAExD,SAASC,mBAAmB,QAAQ,2BAA2B;AAC/D,SAASC,gBAAgB,QAAQ,wBAAwB;AACzD,SAASC,QAAQ,QAAQ,gCAAgC;AAEzDC,KAAKC,IAAI,CAAC,iCAAiC,IAAO,CAAA;QAC9CF,UAAUC,KAAKE,EAAE;IACrB,CAAA;AAEAC,SAAS,CAAC,uBAAuB,EAAEN,oBAAoBO,IAAI,EAAE,EAAE;IAC3D,MAAMC,QAAQ;QAAEC,KAAK;QAAOC,KAAK;IAAM;IACvC,MAAMC,uBAAuB;QACzBC,UAAUT,KAAKE,EAAE;IACrB;IAEA,MAAMQ,YAAgB;QAClB,OAAO,CAAC,aAAa,CAAC;IAC1B;IAEAC,WAAW;QACPX,KAAKY,MAAM,CAACb,UAAUc,kBAAkB,CAAC,IAAMR;IACnD;IAEA,MAAMS,UAAU,IACZnB,qBACI,KAACD;YAASqB,YAAY;gBAAC;oBAAEC,SAASlB;oBAAkBmB,UAAUT;gBAAqB;aAAE;sBACjF,cAAA,KAACX;0BACG,cAAA,KAACa;;;IAKjBQ,KAAK,oBAAoB;QACrBJ;QAEAK,OAAOvB,OAAOwB,SAAS,CAAC,CAAC,aAAa,CAAC,GAAGC,iBAAiB;IAC/D;IAEAH,KAAK,+BAA+B;QAChCJ;QAEAK,OAAOX,qBAAqBC,QAAQ,EAAEa,oBAAoB,CAACjB;IAC/D;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-flag-store.test.d.ts","sourceRoot":"","sources":["../../src/tests/feature-flag-store.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { FeatureFlagStore } from '../feature-flag-store';
|
|
2
|
+
describe(`[launchdarkly-service] ${FeatureFlagStore.name}`, ()=>{
|
|
3
|
+
const subject = ()=>new FeatureFlagStore();
|
|
4
|
+
test('has no flags initially', ()=>{
|
|
5
|
+
expect(subject().flags).toEqual({});
|
|
6
|
+
});
|
|
7
|
+
describe('setFlags', ()=>{
|
|
8
|
+
let store;
|
|
9
|
+
let flags;
|
|
10
|
+
beforeEach(()=>{
|
|
11
|
+
store = new FeatureFlagStore();
|
|
12
|
+
flags = {
|
|
13
|
+
foo: 'bar'
|
|
14
|
+
};
|
|
15
|
+
});
|
|
16
|
+
const subject = (...args)=>store.setFlags(...args);
|
|
17
|
+
test('sets flags', ()=>{
|
|
18
|
+
subject(flags);
|
|
19
|
+
expect(store.flags).toEqual(flags);
|
|
20
|
+
});
|
|
21
|
+
test('stores copy of flags', ()=>{
|
|
22
|
+
subject(flags);
|
|
23
|
+
const originalFlags = {
|
|
24
|
+
...flags
|
|
25
|
+
};
|
|
26
|
+
flags.baz = 'qux';
|
|
27
|
+
expect(store.flags).toEqual(originalFlags);
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
//# sourceMappingURL=feature-flag-store.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tests/feature-flag-store.test.ts"],"sourcesContent":["import { LDFlagSet } from 'launchdarkly-js-client-sdk';\nimport { FeatureFlagStore } from '../feature-flag-store';\n\ndescribe(`[launchdarkly-service] ${FeatureFlagStore.name}`, () => {\n const subject = () => new FeatureFlagStore();\n\n test('has no flags initially', () => {\n expect(subject().flags).toEqual({});\n });\n\n describe('setFlags', () => {\n let store: FeatureFlagStore;\n let flags: LDFlagSet;\n\n beforeEach(() => {\n store = new FeatureFlagStore();\n flags = { foo: 'bar' };\n });\n\n const subject = (...args: Parameters<FeatureFlagStore['setFlags']>) =>\n store.setFlags(...args);\n\n test('sets flags', () => {\n subject(flags);\n\n expect(store.flags).toEqual(flags);\n });\n\n test('stores copy of flags', () => {\n subject(flags);\n\n const originalFlags = { ...flags };\n flags.baz = 'qux';\n\n expect(store.flags).toEqual(originalFlags);\n });\n });\n});\n"],"names":["FeatureFlagStore","describe","name","subject","test","expect","flags","toEqual","store","beforeEach","foo","args","setFlags","originalFlags","baz"],"mappings":"AACA,SAASA,gBAAgB,QAAQ,wBAAwB;AAEzDC,SAAS,CAAC,uBAAuB,EAAED,iBAAiBE,IAAI,EAAE,EAAE;IACxD,MAAMC,UAAU,IAAM,IAAIH;IAE1BI,KAAK,0BAA0B;QAC3BC,OAAOF,UAAUG,KAAK,EAAEC,OAAO,CAAC,CAAC;IACrC;IAEAN,SAAS,YAAY;QACjB,IAAIO;QACJ,IAAIF;QAEJG,WAAW;YACPD,QAAQ,IAAIR;YACZM,QAAQ;gBAAEI,KAAK;YAAM;QACzB;QAEA,MAAMP,UAAU,CAAC,GAAGQ,OAChBH,MAAMI,QAAQ,IAAID;QAEtBP,KAAK,cAAc;YACfD,QAAQG;YAERD,OAAOG,MAAMF,KAAK,EAAEC,OAAO,CAACD;QAChC;QAEAF,KAAK,wBAAwB;YACzBD,QAAQG;YAER,MAAMO,gBAAgB;gBAAE,GAAGP,KAAK;YAAC;YACjCA,MAAMQ,GAAG,GAAG;YAEZT,OAAOG,MAAMF,KAAK,EAAEC,OAAO,CAACM;QAChC;IACJ;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-ld-client.test.d.ts","sourceRoot":"","sources":["../../src/tests/get-ld-client.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { initialize } from 'launchdarkly-js-client-sdk';
|
|
2
|
+
import { getLDClient } from '../get-ld-client';
|
|
3
|
+
jest.mock('launchdarkly-js-client-sdk', ()=>({
|
|
4
|
+
initialize: jest.fn()
|
|
5
|
+
}));
|
|
6
|
+
describe(`[launchdarkly-service] ${getLDClient.name}`, ()=>{
|
|
7
|
+
const mockClient = Symbol('mockClient');
|
|
8
|
+
let config;
|
|
9
|
+
const subject = ()=>getLDClient(config);
|
|
10
|
+
beforeEach(()=>{
|
|
11
|
+
jest.clearAllMocks();
|
|
12
|
+
jest.mocked(initialize).mockImplementation(()=>mockClient);
|
|
13
|
+
config = {
|
|
14
|
+
clientSideID: makeId()
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
function anonymousUserContext() {
|
|
18
|
+
return {
|
|
19
|
+
kind: 'user',
|
|
20
|
+
anonymous: true
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
test('returns new LaunchDarkly client with anonymous user context', ()=>{
|
|
24
|
+
expect(subject()).toBe(mockClient);
|
|
25
|
+
expect(initialize).toHaveBeenCalledWith(config.clientSideID, anonymousUserContext(), undefined);
|
|
26
|
+
});
|
|
27
|
+
describe('when given a context', ()=>{
|
|
28
|
+
beforeEach(()=>config.context = {
|
|
29
|
+
kind: 'multi'
|
|
30
|
+
});
|
|
31
|
+
test('initializes client with context', ()=>{
|
|
32
|
+
subject();
|
|
33
|
+
expect(initialize).toHaveBeenCalledWith(config.clientSideID, config.context, undefined);
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
describe('when given options', ()=>{
|
|
37
|
+
beforeEach(()=>config.options = {
|
|
38
|
+
hash: 'foo'
|
|
39
|
+
});
|
|
40
|
+
test('initializes client with options', ()=>{
|
|
41
|
+
subject();
|
|
42
|
+
expect(initialize).toHaveBeenCalledWith(config.clientSideID, anonymousUserContext(), config.options);
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
describe('when client already exists', ()=>{
|
|
46
|
+
const existingClient = Symbol('existingClient');
|
|
47
|
+
beforeEach(()=>{
|
|
48
|
+
jest.mocked(initialize).mockImplementationOnce(()=>existingClient);
|
|
49
|
+
subject();
|
|
50
|
+
});
|
|
51
|
+
test('returns existing client', ()=>{
|
|
52
|
+
expect(subject()).toBe(existingClient);
|
|
53
|
+
expect(initialize).toHaveBeenCalledTimes(1);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
function makeId() {
|
|
58
|
+
return Math.round(1e6 * Math.random()).toString(36);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
//# sourceMappingURL=get-ld-client.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tests/get-ld-client.test.ts"],"sourcesContent":["import { initialize } from 'launchdarkly-js-client-sdk';\n\nimport { getLDClient } from '../get-ld-client';\n\njest.mock('launchdarkly-js-client-sdk', () => ({\n initialize: jest.fn(),\n}));\n\ndescribe(`[launchdarkly-service] ${getLDClient.name}`, () => {\n const mockClient: any = Symbol('mockClient');\n let config: Parameters<typeof getLDClient>[0];\n\n const subject = () => getLDClient(config);\n\n beforeEach(() => {\n jest.clearAllMocks();\n jest.mocked(initialize).mockImplementation(() => mockClient);\n config = { clientSideID: makeId() };\n });\n\n function anonymousUserContext() {\n return { kind: 'user', anonymous: true };\n }\n\n test('returns new LaunchDarkly client with anonymous user context', () => {\n expect(subject()).toBe(mockClient);\n expect(initialize).toHaveBeenCalledWith(\n config.clientSideID,\n anonymousUserContext(),\n undefined\n );\n });\n\n describe('when given a context', () => {\n beforeEach(() => (config.context = { kind: 'multi' }));\n\n test('initializes client with context', () => {\n subject();\n\n expect(initialize).toHaveBeenCalledWith(config.clientSideID, config.context, undefined);\n });\n });\n\n describe('when given options', () => {\n beforeEach(() => (config.options = { hash: 'foo' }));\n\n test('initializes client with options', () => {\n subject();\n\n expect(initialize).toHaveBeenCalledWith(\n config.clientSideID,\n anonymousUserContext(),\n config.options\n );\n });\n });\n\n describe('when client already exists', () => {\n const existingClient: any = Symbol('existingClient');\n\n beforeEach(() => {\n jest.mocked(initialize).mockImplementationOnce(() => existingClient);\n subject();\n });\n\n test('returns existing client', () => {\n expect(subject()).toBe(existingClient);\n expect(initialize).toHaveBeenCalledTimes(1);\n });\n });\n});\n\nfunction makeId() {\n return Math.round(1e6 * Math.random()).toString(36);\n}\n"],"names":["initialize","getLDClient","jest","mock","fn","describe","name","mockClient","Symbol","config","subject","beforeEach","clearAllMocks","mocked","mockImplementation","clientSideID","makeId","anonymousUserContext","kind","anonymous","test","expect","toBe","toHaveBeenCalledWith","undefined","context","options","hash","existingClient","mockImplementationOnce","toHaveBeenCalledTimes","Math","round","random","toString"],"mappings":"AAAA,SAASA,UAAU,QAAQ,6BAA6B;AAExD,SAASC,WAAW,QAAQ,mBAAmB;AAE/CC,KAAKC,IAAI,CAAC,8BAA8B,IAAO,CAAA;QAC3CH,YAAYE,KAAKE,EAAE;IACvB,CAAA;AAEAC,SAAS,CAAC,uBAAuB,EAAEJ,YAAYK,IAAI,EAAE,EAAE;IACnD,MAAMC,aAAkBC,OAAO;IAC/B,IAAIC;IAEJ,MAAMC,UAAU,IAAMT,YAAYQ;IAElCE,WAAW;QACPT,KAAKU,aAAa;QAClBV,KAAKW,MAAM,CAACb,YAAYc,kBAAkB,CAAC,IAAMP;QACjDE,SAAS;YAAEM,cAAcC;QAAS;IACtC;IAEA,SAASC;QACL,OAAO;YAAEC,MAAM;YAAQC,WAAW;QAAK;IAC3C;IAEAC,KAAK,+DAA+D;QAChEC,OAAOX,WAAWY,IAAI,CAACf;QACvBc,OAAOrB,YAAYuB,oBAAoB,CACnCd,OAAOM,YAAY,EACnBE,wBACAO;IAER;IAEAnB,SAAS,wBAAwB;QAC7BM,WAAW,IAAOF,OAAOgB,OAAO,GAAG;gBAAEP,MAAM;YAAQ;QAEnDE,KAAK,mCAAmC;YACpCV;YAEAW,OAAOrB,YAAYuB,oBAAoB,CAACd,OAAOM,YAAY,EAAEN,OAAOgB,OAAO,EAAED;QACjF;IACJ;IAEAnB,SAAS,sBAAsB;QAC3BM,WAAW,IAAOF,OAAOiB,OAAO,GAAG;gBAAEC,MAAM;YAAM;QAEjDP,KAAK,mCAAmC;YACpCV;YAEAW,OAAOrB,YAAYuB,oBAAoB,CACnCd,OAAOM,YAAY,EACnBE,wBACAR,OAAOiB,OAAO;QAEtB;IACJ;IAEArB,SAAS,8BAA8B;QACnC,MAAMuB,iBAAsBpB,OAAO;QAEnCG,WAAW;YACPT,KAAKW,MAAM,CAACb,YAAY6B,sBAAsB,CAAC,IAAMD;YACrDlB;QACJ;QAEAU,KAAK,2BAA2B;YAC5BC,OAAOX,WAAWY,IAAI,CAACM;YACvBP,OAAOrB,YAAY8B,qBAAqB,CAAC;QAC7C;IACJ;AACJ;AAEA,SAASd;IACL,OAAOe,KAAKC,KAAK,CAAC,MAAMD,KAAKE,MAAM,IAAIC,QAAQ,CAAC;AACpD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ld-provider.test.d.ts","sourceRoot":"","sources":["../../src/tests/ld-provider.test.tsx"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { Log } from '@servicetitan/log-service';
|
|
4
|
+
import { Provider, useDependencies } from '@servicetitan/react-ioc';
|
|
5
|
+
import { render, screen, waitFor } from '@testing-library/react';
|
|
6
|
+
import { act, Fragment } from 'react';
|
|
7
|
+
import { FeatureFlagStore } from '../feature-flag-store';
|
|
8
|
+
import { getLDClient } from '../get-ld-client';
|
|
9
|
+
import { LDProvider } from '../ld-provider';
|
|
10
|
+
import { LD_SERVICE_TOKEN } from '../types';
|
|
11
|
+
function formatProps(props) {
|
|
12
|
+
return Object.entries(props).map(([key, value])=>{
|
|
13
|
+
return `${key}=${value.toString()}`;
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function mockComponent(name) {
|
|
17
|
+
return {
|
|
18
|
+
[name]: ({ children, ...props })=>/*#__PURE__*/ _jsxs(Fragment, {
|
|
19
|
+
children: [
|
|
20
|
+
/*#__PURE__*/ _jsx("div", {
|
|
21
|
+
children: `<${name} ${formatProps(props)} />`
|
|
22
|
+
}),
|
|
23
|
+
children
|
|
24
|
+
]
|
|
25
|
+
})
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
jest.mock('launchdarkly-react-client-sdk', ()=>({
|
|
29
|
+
...mockComponent('LDProvider')
|
|
30
|
+
}));
|
|
31
|
+
jest.mock('../feature-flag-provider', ()=>({
|
|
32
|
+
...mockComponent('FeatureFlagProvider')
|
|
33
|
+
}));
|
|
34
|
+
jest.mock('../get-ld-client', ()=>({
|
|
35
|
+
getLDClient: jest.fn()
|
|
36
|
+
}));
|
|
37
|
+
describe(`[launchdarkly-service] ${LDProvider.name}`, ()=>{
|
|
38
|
+
const log = {
|
|
39
|
+
error: jest.fn()
|
|
40
|
+
};
|
|
41
|
+
const ldClient = {
|
|
42
|
+
on: jest.fn(),
|
|
43
|
+
off: jest.fn(),
|
|
44
|
+
waitUntilReady: jest.fn().mockResolvedValue(undefined),
|
|
45
|
+
waitForInitialization: jest.fn().mockResolvedValue(undefined),
|
|
46
|
+
toString: ()=>'ldClient'
|
|
47
|
+
};
|
|
48
|
+
let singletons;
|
|
49
|
+
let props;
|
|
50
|
+
let providedFeatureFlagStore;
|
|
51
|
+
let renderCount;
|
|
52
|
+
const Component = ()=>{
|
|
53
|
+
[providedFeatureFlagStore] = useDependencies(FeatureFlagStore);
|
|
54
|
+
renderCount += 1;
|
|
55
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
56
|
+
children: '<Component />'
|
|
57
|
+
});
|
|
58
|
+
};
|
|
59
|
+
beforeEach(()=>{
|
|
60
|
+
jest.clearAllMocks();
|
|
61
|
+
jest.mocked(getLDClient).mockReturnValue(ldClient);
|
|
62
|
+
renderCount = 0;
|
|
63
|
+
singletons = [];
|
|
64
|
+
props = {
|
|
65
|
+
clientSideID: 'foo',
|
|
66
|
+
projectName: 'bar'
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
const subject = ()=>{
|
|
70
|
+
return render(/*#__PURE__*/ _jsx(Provider, {
|
|
71
|
+
singletons: singletons,
|
|
72
|
+
children: /*#__PURE__*/ _jsx(LDProvider, {
|
|
73
|
+
...props,
|
|
74
|
+
children: /*#__PURE__*/ _jsx(Component, {})
|
|
75
|
+
})
|
|
76
|
+
}));
|
|
77
|
+
};
|
|
78
|
+
function expectLDProvider(props) {
|
|
79
|
+
if (props) {
|
|
80
|
+
expect(screen.getByText(`<LDProvider ${formatProps(props)} />`)).toBeInTheDocument();
|
|
81
|
+
} else {
|
|
82
|
+
expect(screen.getByText(/<LDProvider .* \/>/)).toBeInTheDocument();
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
test('renders base LDProvider and FeatureFlagProvider after client is ready and initialized', async ()=>{
|
|
86
|
+
subject();
|
|
87
|
+
await waitFor(()=>expectLDProvider({
|
|
88
|
+
clientSideID: props.clientSideID,
|
|
89
|
+
ldClient
|
|
90
|
+
}));
|
|
91
|
+
expect(screen.getByText('<FeatureFlagProvider />')).toBeInTheDocument();
|
|
92
|
+
expect(screen.getByText('<Component />')).toBeInTheDocument();
|
|
93
|
+
expect(ldClient.waitForInitialization).toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
test('provides FeatureFlagStore', async ()=>{
|
|
96
|
+
subject();
|
|
97
|
+
await waitFor(()=>expectLDProvider());
|
|
98
|
+
expect(providedFeatureFlagStore).toBeDefined();
|
|
99
|
+
});
|
|
100
|
+
describe('when waitForInitialization is false', ()=>{
|
|
101
|
+
let initializedCallback;
|
|
102
|
+
beforeEach(()=>{
|
|
103
|
+
var _jest_mocked;
|
|
104
|
+
props.waitForInitialization = false;
|
|
105
|
+
(_jest_mocked = jest.mocked(ldClient.on)) === null || _jest_mocked === void 0 ? void 0 : _jest_mocked.mockImplementation((event, callback)=>{
|
|
106
|
+
if (event === 'initialized') {
|
|
107
|
+
initializedCallback = callback;
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
test('does not wait for client to initialize', async ()=>{
|
|
112
|
+
subject();
|
|
113
|
+
await waitFor(()=>expectLDProvider());
|
|
114
|
+
expect(ldClient.waitForInitialization).not.toHaveBeenCalled();
|
|
115
|
+
});
|
|
116
|
+
test('re-renders when client is initialized', async ()=>{
|
|
117
|
+
subject();
|
|
118
|
+
await waitFor(()=>expectLDProvider());
|
|
119
|
+
expect(renderCount).toBe(1);
|
|
120
|
+
act(()=>initializedCallback === null || initializedCallback === void 0 ? void 0 : initializedCallback());
|
|
121
|
+
expect(renderCount).toBe(2);
|
|
122
|
+
});
|
|
123
|
+
test('deregisters listener when component is unmounted', async ()=>{
|
|
124
|
+
const { unmount } = subject();
|
|
125
|
+
await waitFor(()=>expectLDProvider());
|
|
126
|
+
unmount();
|
|
127
|
+
expect(jest.mocked(ldClient.off)).toHaveBeenCalledWith('initialized', initializedCallback);
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
describe('when initialization fails', ()=>{
|
|
131
|
+
beforeEach(()=>{
|
|
132
|
+
var _jest_mocked;
|
|
133
|
+
(_jest_mocked = jest.mocked(ldClient.waitForInitialization)) === null || _jest_mocked === void 0 ? void 0 : _jest_mocked.mockRejectedValue('Oops!');
|
|
134
|
+
});
|
|
135
|
+
test('renders base LDProvider', async ()=>{
|
|
136
|
+
subject();
|
|
137
|
+
await waitFor(()=>expectLDProvider());
|
|
138
|
+
});
|
|
139
|
+
describe('when log service is provided', ()=>{
|
|
140
|
+
beforeEach(()=>singletons.push({
|
|
141
|
+
provide: Log,
|
|
142
|
+
useValue: log
|
|
143
|
+
}));
|
|
144
|
+
test('logs error', async ()=>{
|
|
145
|
+
subject();
|
|
146
|
+
await waitFor(()=>expectLDProvider());
|
|
147
|
+
expect(log.error).toHaveBeenCalledWith({
|
|
148
|
+
category: 'LaunchDarkly',
|
|
149
|
+
code: 'InitializationFailed',
|
|
150
|
+
error: 'Oops!',
|
|
151
|
+
message: `"${props.projectName}" client failed to initialize`
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe('when LDService is provided', ()=>{
|
|
157
|
+
const ldServiceClient = {
|
|
158
|
+
waitUntilReady: jest.fn().mockResolvedValue(undefined),
|
|
159
|
+
waitForInitialization: jest.fn().mockResolvedValue(undefined),
|
|
160
|
+
toString: ()=>'ldServiceClient'
|
|
161
|
+
};
|
|
162
|
+
const ldService = {
|
|
163
|
+
getClient: jest.fn().mockReturnValue(ldServiceClient)
|
|
164
|
+
};
|
|
165
|
+
beforeEach(()=>{
|
|
166
|
+
singletons === null || singletons === void 0 ? void 0 : singletons.push({
|
|
167
|
+
provide: LD_SERVICE_TOKEN,
|
|
168
|
+
useValue: ldService
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
test('uses LDService client', async ()=>{
|
|
172
|
+
subject();
|
|
173
|
+
await waitFor(()=>expectLDProvider({
|
|
174
|
+
clientSideID: props.clientSideID,
|
|
175
|
+
ldClient: ldServiceClient
|
|
176
|
+
}));
|
|
177
|
+
expect(ldServiceClient.waitForInitialization).toHaveBeenCalled();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
//# sourceMappingURL=ld-provider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tests/ld-provider.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { Log } from '@servicetitan/log-service';\nimport { Provider, useDependencies } from '@servicetitan/react-ioc';\nimport { render, screen, waitFor } from '@testing-library/react';\nimport { LDClient } from 'launchdarkly-js-client-sdk';\nimport { act, FC, Fragment } from 'react';\n\nimport { FeatureFlagStore } from '../feature-flag-store';\nimport { getLDClient } from '../get-ld-client';\nimport { LDProvider } from '../ld-provider';\nimport { LD_SERVICE_TOKEN, LDService } from '../types';\n\nfunction formatProps(props: Record<string, any>) {\n return Object.entries(props).map(([key, value]) => {\n return `${key}=${value.toString()}`;\n });\n}\n\nfunction mockComponent(name: string) {\n return {\n [name]: ({ children, ...props }: any) => (\n <Fragment>\n <div>{`<${name} ${formatProps(props)} />`}</div>\n {children}\n </Fragment>\n ),\n };\n}\n\njest.mock('launchdarkly-react-client-sdk', () => ({\n ...mockComponent('LDProvider'),\n}));\njest.mock('../feature-flag-provider', () => ({\n ...mockComponent('FeatureFlagProvider'),\n}));\njest.mock('../get-ld-client', () => ({\n getLDClient: jest.fn(),\n}));\n\ndescribe(`[launchdarkly-service] ${LDProvider.name}`, () => {\n const log: Partial<Log> = {\n error: jest.fn(),\n };\n const ldClient: Partial<LDClient> & { toString: () => string } = {\n on: jest.fn(),\n off: jest.fn(),\n waitUntilReady: jest.fn().mockResolvedValue(undefined),\n waitForInitialization: jest.fn().mockResolvedValue(undefined),\n toString: () => 'ldClient',\n };\n let singletons: Required<Parameters<typeof Provider>[0]>['singletons'];\n let props: Parameters<typeof LDProvider>[0];\n let providedFeatureFlagStore: FeatureFlagStore;\n let renderCount: number;\n\n const Component: FC = () => {\n [providedFeatureFlagStore] = useDependencies(FeatureFlagStore);\n renderCount += 1;\n return <div>{'<Component />'}</div>;\n };\n\n beforeEach(() => {\n jest.clearAllMocks();\n jest.mocked(getLDClient).mockReturnValue(ldClient as LDClient);\n renderCount = 0;\n singletons = [];\n props = { clientSideID: 'foo', projectName: 'bar' };\n });\n\n const subject = () => {\n return render(\n <Provider singletons={singletons}>\n <LDProvider {...props}>\n <Component />\n </LDProvider>\n </Provider>\n );\n };\n\n function expectLDProvider(props?: Record<string, any>) {\n if (props) {\n expect(screen.getByText(`<LDProvider ${formatProps(props)} />`)).toBeInTheDocument();\n } else {\n expect(screen.getByText(/<LDProvider .* \\/>/)).toBeInTheDocument();\n }\n }\n\n test('renders base LDProvider and FeatureFlagProvider after client is ready and initialized', async () => {\n subject();\n\n await waitFor(() => expectLDProvider({ clientSideID: props.clientSideID, ldClient }));\n\n expect(screen.getByText('<FeatureFlagProvider />')).toBeInTheDocument();\n expect(screen.getByText('<Component />')).toBeInTheDocument();\n expect(ldClient.waitForInitialization).toHaveBeenCalled();\n });\n\n test('provides FeatureFlagStore', async () => {\n subject();\n\n await waitFor(() => expectLDProvider());\n\n expect(providedFeatureFlagStore).toBeDefined();\n });\n\n describe('when waitForInitialization is false', () => {\n let initializedCallback: Function;\n\n beforeEach(() => {\n props.waitForInitialization = false;\n jest.mocked(ldClient.on)?.mockImplementation((event, callback) => {\n if (event === 'initialized') {\n initializedCallback = callback;\n }\n });\n });\n\n test('does not wait for client to initialize', async () => {\n subject();\n\n await waitFor(() => expectLDProvider());\n\n expect(ldClient.waitForInitialization).not.toHaveBeenCalled();\n });\n\n test('re-renders when client is initialized', async () => {\n subject();\n\n await waitFor(() => expectLDProvider());\n expect(renderCount).toBe(1);\n\n act(() => initializedCallback?.());\n expect(renderCount).toBe(2);\n });\n\n test('deregisters listener when component is unmounted', async () => {\n const { unmount } = subject();\n\n await waitFor(() => expectLDProvider());\n\n unmount();\n\n expect(jest.mocked(ldClient.off)).toHaveBeenCalledWith(\n 'initialized',\n initializedCallback\n );\n });\n });\n\n describe('when initialization fails', () => {\n beforeEach(() => {\n jest.mocked(ldClient.waitForInitialization)?.mockRejectedValue('Oops!');\n });\n\n test('renders base LDProvider', async () => {\n subject();\n\n await waitFor(() => expectLDProvider());\n });\n\n describe('when log service is provided', () => {\n beforeEach(() => singletons.push({ provide: Log, useValue: log }));\n\n test('logs error', async () => {\n subject();\n\n await waitFor(() => expectLDProvider());\n\n expect(log.error).toHaveBeenCalledWith({\n category: 'LaunchDarkly',\n code: 'InitializationFailed',\n error: 'Oops!',\n message: `\"${props.projectName}\" client failed to initialize`,\n });\n });\n });\n });\n\n describe('when LDService is provided', () => {\n const ldServiceClient: Partial<LDClient> & { toString: () => string } = {\n waitUntilReady: jest.fn().mockResolvedValue(undefined),\n waitForInitialization: jest.fn().mockResolvedValue(undefined),\n toString: () => 'ldServiceClient',\n };\n const ldService: LDService = {\n getClient: jest.fn().mockReturnValue(ldServiceClient),\n };\n\n beforeEach(() => {\n singletons?.push({ provide: LD_SERVICE_TOKEN, useValue: ldService });\n });\n\n test('uses LDService client', async () => {\n subject();\n\n await waitFor(() =>\n expectLDProvider({ clientSideID: props.clientSideID, ldClient: ldServiceClient })\n );\n\n expect(ldServiceClient.waitForInitialization).toHaveBeenCalled();\n });\n });\n});\n"],"names":["Log","Provider","useDependencies","render","screen","waitFor","act","Fragment","FeatureFlagStore","getLDClient","LDProvider","LD_SERVICE_TOKEN","formatProps","props","Object","entries","map","key","value","toString","mockComponent","name","children","div","jest","mock","fn","describe","log","error","ldClient","on","off","waitUntilReady","mockResolvedValue","undefined","waitForInitialization","singletons","providedFeatureFlagStore","renderCount","Component","beforeEach","clearAllMocks","mocked","mockReturnValue","clientSideID","projectName","subject","expectLDProvider","expect","getByText","toBeInTheDocument","test","toHaveBeenCalled","toBeDefined","initializedCallback","mockImplementation","event","callback","not","toBe","unmount","toHaveBeenCalledWith","mockRejectedValue","push","provide","useValue","category","code","message","ldServiceClient","ldService","getClient"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ld-service-provider.test.d.ts","sourceRoot":"","sources":["../../src/tests/ld-service-provider.test.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Provider, useDependencies } from '@servicetitan/react-ioc';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { getLDClient } from '../get-ld-client';
|
|
5
|
+
import { LDServiceProvider } from '../ld-service-provider';
|
|
6
|
+
import { LD_SERVICE_TOKEN } from '../types';
|
|
7
|
+
describe(`[launchdarkly-service] ${LDServiceProvider.name}`, ()=>{
|
|
8
|
+
let providedLDService;
|
|
9
|
+
let singletons;
|
|
10
|
+
const Component = ()=>{
|
|
11
|
+
[providedLDService] = useDependencies(LD_SERVICE_TOKEN);
|
|
12
|
+
return null;
|
|
13
|
+
};
|
|
14
|
+
beforeEach(()=>singletons = []);
|
|
15
|
+
const subject = ()=>{
|
|
16
|
+
return render(/*#__PURE__*/ _jsx(Provider, {
|
|
17
|
+
singletons: singletons,
|
|
18
|
+
children: /*#__PURE__*/ _jsx(LDServiceProvider, {
|
|
19
|
+
children: /*#__PURE__*/ _jsx(Component, {})
|
|
20
|
+
})
|
|
21
|
+
}));
|
|
22
|
+
};
|
|
23
|
+
test('provides LDService instance', ()=>{
|
|
24
|
+
subject();
|
|
25
|
+
expect(providedLDService).toEqual({
|
|
26
|
+
getClient: getLDClient
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
describe('when LDService is already provided', ()=>{
|
|
30
|
+
const ldService = Symbol('ldService');
|
|
31
|
+
beforeEach(()=>singletons === null || singletons === void 0 ? void 0 : singletons.push({
|
|
32
|
+
provide: LD_SERVICE_TOKEN,
|
|
33
|
+
useValue: ldService
|
|
34
|
+
}));
|
|
35
|
+
test('provides existing LDService', ()=>{
|
|
36
|
+
subject();
|
|
37
|
+
expect(providedLDService).toBe(ldService);
|
|
38
|
+
});
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
//# sourceMappingURL=ld-service-provider.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tests/ld-service-provider.test.tsx"],"sourcesContent":["import { Provider, useDependencies } from '@servicetitan/react-ioc';\nimport { render } from '@testing-library/react';\nimport { FC } from 'react';\n\nimport { getLDClient } from '../get-ld-client';\nimport { LDServiceProvider } from '../ld-service-provider';\nimport { LD_SERVICE_TOKEN, LDService } from '../types';\n\ndescribe(`[launchdarkly-service] ${LDServiceProvider.name}`, () => {\n let providedLDService: LDService;\n let singletons: Parameters<typeof Provider>[0]['singletons'];\n\n const Component: FC = () => {\n [providedLDService] = useDependencies(LD_SERVICE_TOKEN);\n return null;\n };\n\n beforeEach(() => (singletons = []));\n\n const subject = () => {\n return render(\n <Provider singletons={singletons}>\n <LDServiceProvider>\n <Component />\n </LDServiceProvider>\n </Provider>\n );\n };\n\n test('provides LDService instance', () => {\n subject();\n\n expect(providedLDService).toEqual({\n getClient: getLDClient,\n });\n });\n\n describe('when LDService is already provided', () => {\n const ldService = Symbol('ldService');\n\n beforeEach(() => singletons?.push({ provide: LD_SERVICE_TOKEN, useValue: ldService }));\n\n test('provides existing LDService', () => {\n subject();\n\n expect(providedLDService).toBe(ldService);\n });\n });\n});\n"],"names":["Provider","useDependencies","render","getLDClient","LDServiceProvider","LD_SERVICE_TOKEN","describe","name","providedLDService","singletons","Component","beforeEach","subject","test","expect","toEqual","getClient","ldService","Symbol","push","provide","useValue","toBe"],"mappings":";AAAA,SAASA,QAAQ,EAAEC,eAAe,QAAQ,0BAA0B;AACpE,SAASC,MAAM,QAAQ,yBAAyB;AAGhD,SAASC,WAAW,QAAQ,mBAAmB;AAC/C,SAASC,iBAAiB,QAAQ,yBAAyB;AAC3D,SAASC,gBAAgB,QAAmB,WAAW;AAEvDC,SAAS,CAAC,uBAAuB,EAAEF,kBAAkBG,IAAI,EAAE,EAAE;IACzD,IAAIC;IACJ,IAAIC;IAEJ,MAAMC,YAAgB;QAClB,CAACF,kBAAkB,GAAGP,gBAAgBI;QACtC,OAAO;IACX;IAEAM,WAAW,IAAOF,aAAa,EAAE;IAEjC,MAAMG,UAAU;QACZ,OAAOV,qBACH,KAACF;YAASS,YAAYA;sBAClB,cAAA,KAACL;0BACG,cAAA,KAACM;;;IAIjB;IAEAG,KAAK,+BAA+B;QAChCD;QAEAE,OAAON,mBAAmBO,OAAO,CAAC;YAC9BC,WAAWb;QACf;IACJ;IAEAG,SAAS,sCAAsC;QAC3C,MAAMW,YAAYC,OAAO;QAEzBP,WAAW,IAAMF,uBAAAA,iCAAAA,WAAYU,IAAI,CAAC;gBAAEC,SAASf;gBAAkBgB,UAAUJ;YAAU;QAEnFJ,KAAK,+BAA+B;YAChCD;YAEAE,OAAON,mBAAmBc,IAAI,CAACL;QACnC;IACJ;AACJ"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"with-feature-flag.test.d.ts","sourceRoot":"","sources":["../../src/tests/with-feature-flag.test.tsx"],"names":[],"mappings":"AAAA,OAAO,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import '@testing-library/jest-dom';
|
|
3
|
+
import { render, screen } from '@testing-library/react';
|
|
4
|
+
import { useFlags } from 'launchdarkly-react-client-sdk';
|
|
5
|
+
import { WithFeatureFlag } from '../with-feature-flag';
|
|
6
|
+
jest.mock('launchdarkly-react-client-sdk', ()=>({
|
|
7
|
+
useFlags: jest.fn()
|
|
8
|
+
}));
|
|
9
|
+
describe(`[launchdarkly-service] ${WithFeatureFlag.name}`, ()=>{
|
|
10
|
+
const flagKey = 'foo';
|
|
11
|
+
const childContent = 'Flag is ON';
|
|
12
|
+
let props;
|
|
13
|
+
let flagValue;
|
|
14
|
+
beforeEach(()=>{
|
|
15
|
+
props = {
|
|
16
|
+
flagKey,
|
|
17
|
+
children: childContent
|
|
18
|
+
};
|
|
19
|
+
jest.mocked(useFlags).mockImplementation(()=>({
|
|
20
|
+
[flagKey]: flagValue
|
|
21
|
+
}));
|
|
22
|
+
});
|
|
23
|
+
const subject = ()=>render(/*#__PURE__*/ _jsx(WithFeatureFlag, {
|
|
24
|
+
...props
|
|
25
|
+
}));
|
|
26
|
+
function itRendersNothing() {
|
|
27
|
+
test('renders nothing', ()=>{
|
|
28
|
+
subject();
|
|
29
|
+
expect(screen.queryByText(childContent)).not.toBeInTheDocument();
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
function itRendersChildren() {
|
|
33
|
+
test('renders children', ()=>{
|
|
34
|
+
subject();
|
|
35
|
+
expect(screen.getByText(childContent)).toBeInTheDocument();
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
itRendersNothing();
|
|
39
|
+
describe('when flag is turned on', ()=>{
|
|
40
|
+
beforeEach(()=>flagValue = true);
|
|
41
|
+
itRendersChildren();
|
|
42
|
+
describe('with on prop', ()=>{
|
|
43
|
+
const onContent = 'Flag is ENABLED';
|
|
44
|
+
beforeEach(()=>props.on = ()=>onContent);
|
|
45
|
+
test('renders on content', ()=>{
|
|
46
|
+
subject();
|
|
47
|
+
expect(screen.getByText(onContent)).toBeInTheDocument();
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
describe('when flag is turned off', ()=>{
|
|
52
|
+
beforeEach(()=>flagValue = false);
|
|
53
|
+
itRendersNothing();
|
|
54
|
+
describe('with off prop', ()=>{
|
|
55
|
+
const offContent = 'flag is OFF';
|
|
56
|
+
beforeEach(()=>props.off = ()=>offContent);
|
|
57
|
+
test('renders off content', ()=>{
|
|
58
|
+
subject();
|
|
59
|
+
expect(screen.getByText(offContent)).toBeInTheDocument();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
describe('with flag value', ()=>{
|
|
64
|
+
beforeEach(()=>props.value = 'bar');
|
|
65
|
+
itRendersNothing();
|
|
66
|
+
describe('when flag matches value', ()=>{
|
|
67
|
+
beforeEach(()=>flagValue = props.value);
|
|
68
|
+
itRendersChildren();
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
//# sourceMappingURL=with-feature-flag.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/tests/with-feature-flag.test.tsx"],"sourcesContent":["import '@testing-library/jest-dom';\nimport { render, screen } from '@testing-library/react';\nimport { LDFlagValue, useFlags } from 'launchdarkly-react-client-sdk';\n\nimport { WithFeatureFlag } from '../with-feature-flag';\n\njest.mock('launchdarkly-react-client-sdk', () => ({\n useFlags: jest.fn(),\n}));\n\ndescribe(`[launchdarkly-service] ${WithFeatureFlag.name}`, () => {\n const flagKey = 'foo';\n const childContent = 'Flag is ON';\n let props: Parameters<typeof WithFeatureFlag>[0];\n let flagValue: LDFlagValue;\n\n beforeEach(() => {\n props = { flagKey, children: childContent };\n jest.mocked(useFlags).mockImplementation(() => ({ [flagKey]: flagValue }));\n });\n\n const subject = () => render(<WithFeatureFlag {...props} />);\n\n function itRendersNothing() {\n test('renders nothing', () => {\n subject();\n\n expect(screen.queryByText(childContent)).not.toBeInTheDocument();\n });\n }\n\n function itRendersChildren() {\n test('renders children', () => {\n subject();\n\n expect(screen.getByText(childContent)).toBeInTheDocument();\n });\n }\n\n itRendersNothing();\n\n describe('when flag is turned on', () => {\n beforeEach(() => (flagValue = true));\n\n itRendersChildren();\n\n describe('with on prop', () => {\n const onContent = 'Flag is ENABLED';\n\n beforeEach(() => (props.on = () => onContent));\n\n test('renders on content', () => {\n subject();\n\n expect(screen.getByText(onContent)).toBeInTheDocument();\n });\n });\n });\n\n describe('when flag is turned off', () => {\n beforeEach(() => (flagValue = false));\n\n itRendersNothing();\n\n describe('with off prop', () => {\n const offContent = 'flag is OFF';\n\n beforeEach(() => (props.off = () => offContent));\n\n test('renders off content', () => {\n subject();\n\n expect(screen.getByText(offContent)).toBeInTheDocument();\n });\n });\n });\n\n describe('with flag value', () => {\n beforeEach(() => (props.value = 'bar'));\n\n itRendersNothing();\n\n describe('when flag matches value', () => {\n beforeEach(() => (flagValue = props.value));\n\n itRendersChildren();\n });\n });\n});\n"],"names":["render","screen","useFlags","WithFeatureFlag","jest","mock","fn","describe","name","flagKey","childContent","props","flagValue","beforeEach","children","mocked","mockImplementation","subject","itRendersNothing","test","expect","queryByText","not","toBeInTheDocument","itRendersChildren","getByText","onContent","on","offContent","off","value"],"mappings":";AAAA,OAAO,4BAA4B;AACnC,SAASA,MAAM,EAAEC,MAAM,QAAQ,yBAAyB;AACxD,SAAsBC,QAAQ,QAAQ,gCAAgC;AAEtE,SAASC,eAAe,QAAQ,uBAAuB;AAEvDC,KAAKC,IAAI,CAAC,iCAAiC,IAAO,CAAA;QAC9CH,UAAUE,KAAKE,EAAE;IACrB,CAAA;AAEAC,SAAS,CAAC,uBAAuB,EAAEJ,gBAAgBK,IAAI,EAAE,EAAE;IACvD,MAAMC,UAAU;IAChB,MAAMC,eAAe;IACrB,IAAIC;IACJ,IAAIC;IAEJC,WAAW;QACPF,QAAQ;YAAEF;YAASK,UAAUJ;QAAa;QAC1CN,KAAKW,MAAM,CAACb,UAAUc,kBAAkB,CAAC,IAAO,CAAA;gBAAE,CAACP,QAAQ,EAAEG;YAAU,CAAA;IAC3E;IAEA,MAAMK,UAAU,IAAMjB,qBAAO,KAACG;YAAiB,GAAGQ,KAAK;;IAEvD,SAASO;QACLC,KAAK,mBAAmB;YACpBF;YAEAG,OAAOnB,OAAOoB,WAAW,CAACX,eAAeY,GAAG,CAACC,iBAAiB;QAClE;IACJ;IAEA,SAASC;QACLL,KAAK,oBAAoB;YACrBF;YAEAG,OAAOnB,OAAOwB,SAAS,CAACf,eAAea,iBAAiB;QAC5D;IACJ;IAEAL;IAEAX,SAAS,0BAA0B;QAC/BM,WAAW,IAAOD,YAAY;QAE9BY;QAEAjB,SAAS,gBAAgB;YACrB,MAAMmB,YAAY;YAElBb,WAAW,IAAOF,MAAMgB,EAAE,GAAG,IAAMD;YAEnCP,KAAK,sBAAsB;gBACvBF;gBAEAG,OAAOnB,OAAOwB,SAAS,CAACC,YAAYH,iBAAiB;YACzD;QACJ;IACJ;IAEAhB,SAAS,2BAA2B;QAChCM,WAAW,IAAOD,YAAY;QAE9BM;QAEAX,SAAS,iBAAiB;YACtB,MAAMqB,aAAa;YAEnBf,WAAW,IAAOF,MAAMkB,GAAG,GAAG,IAAMD;YAEpCT,KAAK,uBAAuB;gBACxBF;gBAEAG,OAAOnB,OAAOwB,SAAS,CAACG,aAAaL,iBAAiB;YAC1D;QACJ;IACJ;IAEAhB,SAAS,mBAAmB;QACxBM,WAAW,IAAOF,MAAMmB,KAAK,GAAG;QAEhCZ;QAEAX,SAAS,2BAA2B;YAChCM,WAAW,IAAOD,YAAYD,MAAMmB,KAAK;YAEzCN;QACJ;IACJ;AACJ"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/launchdarkly-service",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.2.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"homepage": "https://docs.st.dev/docs/frontend/launchdarkly-service",
|
|
6
6
|
"repository": {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"src"
|
|
17
17
|
],
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"@servicetitan/log-service": "31.
|
|
20
|
-
"@servicetitan/react-ioc": "31.
|
|
19
|
+
"@servicetitan/log-service": "31.2.0",
|
|
20
|
+
"@servicetitan/react-ioc": "31.2.0",
|
|
21
21
|
"@testing-library/dom": "^10.4.0",
|
|
22
22
|
"@testing-library/jest-dom": "^6.6.3",
|
|
23
23
|
"@testing-library/react": "^16.3.0",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"react": "~18.3.1"
|
|
28
28
|
},
|
|
29
29
|
"peerDependencies": {
|
|
30
|
-
"@servicetitan/log-service": "31.
|
|
31
|
-
"@servicetitan/react-ioc": "31.
|
|
30
|
+
"@servicetitan/log-service": "31.2.0",
|
|
31
|
+
"@servicetitan/react-ioc": "31.2.0",
|
|
32
32
|
"launchdarkly-js-client-sdk": "3.5.0",
|
|
33
33
|
"launchdarkly-react-client-sdk": "3.6.1",
|
|
34
34
|
"mobx": ">= 6.13.7",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"cli": {
|
|
41
41
|
"webpack": false
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "a12efe0333352598f98e5f8772458c8b8d64aa74"
|
|
44
44
|
}
|