import React from 'react';
import {mount} from 'enzyme';
import Projects from 'app/utils/projects';
import ProjectsStore from 'app/stores/projectsStore';
describe('utils.projects', function() {
const renderer = jest.fn(() => null);
const createWrapper = props =>
mount(); // eslint-disable-line
beforeEach(function() {
renderer.mockClear();
MockApiClient.clearMockResponses();
ProjectsStore.loadInitialData([
TestStubs.Project({id: '1', slug: 'foo'}),
TestStubs.Project({id: '2', slug: 'bar'}),
]);
});
afterEach(async function() {
ProjectsStore.loadInitialData([]);
await tick();
});
describe('with predefined list of slugs', function() {
it('gets projects that are in the ProjectsStore ', async function() {
const wrapper = createWrapper({slugs: ['foo', 'bar']});
// This is initial state
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: null,
hasMore: null,
projects: [
expect.objectContaining({
id: '1',
slug: 'foo',
}),
expect.objectContaining({
id: '2',
slug: 'bar',
}),
],
})
);
await tick();
wrapper.update();
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: null,
hasMore: null,
projects: [
expect.objectContaining({
id: '1',
slug: 'foo',
}),
expect.objectContaining({
id: '2',
slug: 'bar',
}),
],
})
);
});
it('fetches projects from API if not found in store', async function() {
const request = MockApiClient.addMockResponse({
url: '/organizations/org-slug/projects/',
query: {
query: 'slug:a slug:b',
},
body: [
TestStubs.Project({
id: '100',
slug: 'a',
}),
TestStubs.Project({
id: '101',
slug: 'b',
}),
],
});
const wrapper = createWrapper({slugs: ['foo', 'a', 'b']});
// This is initial state
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: true,
isIncomplete: null,
hasMore: null,
projects: [
{slug: 'a'},
{slug: 'b'},
expect.objectContaining({
id: '1',
slug: 'foo',
}),
],
})
);
await tick();
wrapper.update();
expect(request).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
query: {
query: 'slug:a slug:b',
},
})
);
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: false,
hasMore: null,
projects: [
expect.objectContaining({
id: '100',
slug: 'a',
}),
expect.objectContaining({
id: '101',
slug: 'b',
}),
expect.objectContaining({
id: '1',
slug: 'foo',
}),
],
})
);
});
it('only has partial results from API', async function() {
const request = MockApiClient.addMockResponse({
url: '/organizations/org-slug/projects/',
body: [
TestStubs.Project({
id: '100',
slug: 'a',
}),
],
});
const wrapper = createWrapper({slugs: ['foo', 'a', 'b']});
// This is initial state
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: true,
isIncomplete: null,
hasMore: null,
projects: [
{slug: 'a'},
{slug: 'b'},
expect.objectContaining({
id: '1',
slug: 'foo',
}),
],
})
);
await tick();
wrapper.update();
expect(request).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
query: {
query: 'slug:a slug:b',
},
})
);
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: true,
hasMore: null,
projects: [
expect.objectContaining({
id: '100',
slug: 'a',
}),
{
slug: 'b',
},
expect.objectContaining({
id: '1',
slug: 'foo',
}),
],
})
);
});
});
describe('with no pre-defined projects', function() {
let request;
beforeEach(async function() {
request = MockApiClient.addMockResponse({
url: '/organizations/org-slug/projects/',
body: [
TestStubs.Project({
id: '100',
slug: 'a',
}),
TestStubs.Project({
id: '101',
slug: 'b',
}),
],
headers: {
Link:
'; rel="previous"; results="true"; cursor="1443575731:0:1", ' +
'; rel="next"; results="true"; cursor="1443575731:0:0',
},
});
ProjectsStore.loadInitialData([]);
await tick();
});
it('fetches projects from API', async function() {
const wrapper = createWrapper();
// This is initial state
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: true,
isIncomplete: null,
hasMore: null,
projects: [],
})
);
await tick();
wrapper.update();
expect(request).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
query: {},
})
);
expect(renderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: null,
hasMore: true,
projects: [
expect.objectContaining({
id: '100',
slug: 'a',
}),
expect.objectContaining({
id: '101',
slug: 'b',
}),
],
})
);
});
it('queries API for more projects and replaces results', async function() {
const myRenderer = jest.fn(({onSearch}) => (
onSearch(target.value)} />
));
const wrapper = createWrapper({children: myRenderer});
// This is initial state
expect(myRenderer).toHaveBeenCalledWith(
expect.objectContaining({
fetching: true,
isIncomplete: null,
hasMore: null,
projects: [],
})
);
await tick();
wrapper.update();
request.mockClear();
request = MockApiClient.addMockResponse({
url: '/organizations/org-slug/projects/',
body: [
TestStubs.Project({
id: '102',
slug: 'test1',
}),
TestStubs.Project({
id: '103',
slug: 'test2',
}),
],
});
wrapper.find('input').simulate('change', {target: {value: 'test'}});
expect(request).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
query: {
query: 'test',
},
})
);
await tick();
wrapper.update();
expect(myRenderer).toHaveBeenLastCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: null,
hasMore: false,
projects: [
expect.objectContaining({
id: '102',
slug: 'test1',
}),
expect.objectContaining({
id: '103',
slug: 'test2',
}),
],
})
);
});
it('queries API for more projects and appends results', async function() {
const myRenderer = jest.fn(({onSearch}) => (
onSearch(target.value, {append: true})} />
));
const wrapper = createWrapper({children: myRenderer});
await tick();
wrapper.update();
request.mockClear();
request = MockApiClient.addMockResponse({
url: '/organizations/org-slug/projects/',
body: [
TestStubs.Project({
id: '102',
slug: 'test1',
}),
TestStubs.Project({
id: '103',
slug: 'test2',
}),
],
});
wrapper.find('input').simulate('change', {target: {value: 'test'}});
expect(request).toHaveBeenCalledWith(
expect.anything(),
expect.objectContaining({
query: {
query: 'test',
},
})
);
await tick();
wrapper.update();
expect(myRenderer).toHaveBeenLastCalledWith(
expect.objectContaining({
fetching: false,
isIncomplete: null,
hasMore: false,
projects: [
expect.objectContaining({
id: '100',
slug: 'a',
}),
expect.objectContaining({
id: '101',
slug: 'b',
}),
expect.objectContaining({
id: '102',
slug: 'test1',
}),
expect.objectContaining({
id: '103',
slug: 'test2',
}),
],
})
);
// Should not have duplicates
wrapper.find('input').simulate('change', {target: {value: 'test'}});
await tick();
wrapper.update();
expect(myRenderer).toHaveBeenLastCalledWith(
expect.objectContaining({
projects: [
expect.objectContaining({
id: '100',
slug: 'a',
}),
expect.objectContaining({
id: '101',
slug: 'b',
}),
expect.objectContaining({
id: '102',
slug: 'test1',
}),
expect.objectContaining({
id: '103',
slug: 'test2',
}),
],
})
);
});
});
});