Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable graceful failure #54

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const initialize = ({ clientSideId, user, ldOptions, readyBeforeIdentify
},
flags: {},
ready: false,
error: null,
};

ldClient.on('ready', () => {
Expand All @@ -36,6 +37,12 @@ export const initialize = ({ clientSideId, user, ldOptions, readyBeforeIdentify
...formatFlags(flattenedFlags),
};
});

ldClient.on('error', (e) => {
$ld.error = e;
throw e;
});

return $ld;
};

Expand Down
192 changes: 109 additions & 83 deletions tests/unit/vue-ld.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,11 @@ describe('VueLd Plugin', () => {
let localVue;
let server;
let warnSpy;
let wrapper;

beforeEach(() => {
localVue = createLocalVue();
server = sinon.createFakeServer();
server.autoRespond = true;
server.autoRespondAfter = 0;
server.respondWith([
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(flagsResponse),
]);
warnSpy = jest.spyOn(console, 'warn').mockImplementation(() => {});
errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
});
Expand All @@ -33,99 +28,130 @@ describe('VueLd Plugin', () => {
errorSpy.mockRestore();
});

let wrapper;
it('changes ready state before identify', async () => {
localVue.use(VueLd, vueLdOptions);
wrapper = mount(Component, {
localVue,
describe('Success states', () => {
beforeEach(() => {
server.autoRespond = true;
server.autoRespondAfter = 0;
server.respondWith([
200,
{ 'Content-Type': 'application/json' },
JSON.stringify(flagsResponse),
]);
});
expect(wrapper.vm.$ld).not.toBe(undefined);
expect(wrapper.vm.$ld.ready).toBe(false);
it('changes ready state before identify', async () => {
localVue.use(VueLd, vueLdOptions);
wrapper = mount(Component, {
localVue,
});
expect(wrapper.vm.$ld).not.toBe(undefined);
expect(wrapper.vm.$ld.ready).toBe(false);

await ldClientReady(wrapper);
await ldClientReady(wrapper);

expect(wrapper.vm.$ld.ready).toBe(true);
});

it('changes ready state after identify', async () => {
localVue.use(VueLd, {
...vueLdOptions,
readyBeforeIdentify: false,
});
wrapper = mount(Component, {
localVue,
expect(wrapper.vm.$ld.ready).toBe(true);
});

expect(wrapper.vm.$ld).not.toBe(undefined);
expect(wrapper.vm.$ld.ready).toBe(false);

await ldClientReady(wrapper);
expect(wrapper.vm.$ld.ready).toBe(false);
await wrapper.vm.$ld.identify({
newUser: {
key: 'anonymous2',
email: 'anonymous2@test.com',
name: 'Anonymous User 2',
},
});
expect(wrapper.vm.$ld.ready).toBe(true);
});
it('changes ready state after identify', async () => {
localVue.use(VueLd, {
...vueLdOptions,
readyBeforeIdentify: false,
});
wrapper = mount(Component, {
localVue,
});

it('calls vueLdCallback after ready with correct context', async () => {
localVue.use(VueLd, {
...vueLdOptions,
readyBeforeIdentify: false,
});
wrapper = mount(Component, {
localVue,
});
const vueLdCallback = jest.fn();
await ldClientReady(wrapper);
await wrapper.vm.$ld.identify(
{
expect(wrapper.vm.$ld).not.toBe(undefined);
expect(wrapper.vm.$ld.ready).toBe(false);

await ldClientReady(wrapper);
expect(wrapper.vm.$ld.ready).toBe(false);
await wrapper.vm.$ld.identify({
newUser: {
key: 'anonymous2',
email: 'anonymous2@test.com',
name: 'Anonymous User 2',
},
},
vueLdCallback
);

expect(vueLdCallback).toBeCalled();
expect(vueLdCallback.mock.instances[0]).toBe(wrapper.vm.$ld);
});
});
expect(wrapper.vm.$ld.ready).toBe(true);
});

it('stubs flags when passed the option', async () => {
localVue.use(VueLd, {
...vueLdOptions,
/*
Using a proxy like this will allow you to return true for everything
not explicitly on the base object or set later.
*/
flagsStub: new Proxy(
it('calls vueLdCallback after ready with correct context', async () => {
localVue.use(VueLd, {
...vueLdOptions,
readyBeforeIdentify: false,
});
wrapper = mount(Component, {
localVue,
});
const vueLdCallback = jest.fn();
await ldClientReady(wrapper);
await wrapper.vm.$ld.identify(
{
never: false,
},
{
get(obj, prop) {
const value = obj[prop];
return value === undefined ? true : value;
newUser: {
key: 'anonymous2',
email: 'anonymous2@test.com',
name: 'Anonymous User 2',
},
}
),
});
wrapper = mount(Component, {
localVue,
},
vueLdCallback
);

expect(vueLdCallback).toBeCalled();
expect(vueLdCallback.mock.instances[0]).toBe(wrapper.vm.$ld);
});

expect(wrapper.vm.$ld.flags.never).toBe(false);
expect(wrapper.vm.$ld.flags.anythingElse).toBe(true);
it('stubs flags when passed the option', async () => {
localVue.use(VueLd, {
...vueLdOptions,
/*
Using a proxy like this will allow you to return true for everything
not explicitly on the base object or set later.
*/
flagsStub: new Proxy(
{
never: false,
},
{
get(obj, prop) {
const value = obj[prop];
return value === undefined ? true : value;
},
}
),
});
wrapper = mount(Component, {
localVue,
});

expect(wrapper.vm.$ld.flags.never).toBe(false);
expect(wrapper.vm.$ld.flags.anythingElse).toBe(true);

wrapper.vm.$ld.flags.neverLater = false;
expect(wrapper.vm.$ld.flags.neverLater).toBe(false);
wrapper.vm.$ld.flags.neverLater = false;
expect(wrapper.vm.$ld.flags.neverLater).toBe(false);

delete wrapper.vm.$ld.flags.neverLater;
expect(wrapper.vm.$ld.flags.anythingElse).toBe(true);
delete wrapper.vm.$ld.flags.neverLater;
expect(wrapper.vm.$ld.flags.anythingElse).toBe(true);
});
});

describe('Error states', () => {
beforeEach(() => {
server.autoRespond = true;
server.autoRespondAfter = 0;
server.respondWith([
400,
{ 'Content-Type': 'application/json' },
JSON.stringify({ message: 'Bad Request' }),
]);
});

it.only('should set error when ldClient emits an error', async () => {
benjamin-t-frost marked this conversation as resolved.
Show resolved Hide resolved
localVue.use(VueLd, vueLdOptions);
wrapper = mount(Component, {
localVue,
});
await ldClientReady(wrapper);
expect(wrapper.vm.$ld.error).toBeTruthy();
});
});
});