sforkowany z mirror/soapbox
Merge branch 'test-blocks' into 'develop'
Convert blocks action to TypeScript See merge request soapbox-pub/soapbox-fe!1454ci-review-rules
commit
747c393c13
|
@ -0,0 +1,8 @@
|
|||
[
|
||||
{
|
||||
"id": "22",
|
||||
"username": "twoods",
|
||||
"acct": "twoods",
|
||||
"display_name": "Tiger Woods"
|
||||
}
|
||||
]
|
|
@ -1,6 +1,7 @@
|
|||
import { jest } from '@jest/globals';
|
||||
import { AxiosInstance } from 'axios';
|
||||
import { AxiosInstance, AxiosResponse } from 'axios';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import LinkHeader from 'http-link-header';
|
||||
|
||||
const api = jest.requireActual('../api') as Record<string, Function>;
|
||||
let mocks: Array<Function> = [];
|
||||
|
@ -15,6 +16,10 @@ const setupMock = (axios: AxiosInstance) => {
|
|||
|
||||
export const staticClient = api.staticClient;
|
||||
|
||||
export const getLinks = (response: AxiosResponse): LinkHeader => {
|
||||
return new LinkHeader(response.headers?.link);
|
||||
};
|
||||
|
||||
export const baseClient = (...params: any[]) => {
|
||||
const axios = api.baseClient(...params);
|
||||
setupMock(axios);
|
||||
|
|
|
@ -0,0 +1,183 @@
|
|||
import { __stub } from 'soapbox/api';
|
||||
import { mockStore } from 'soapbox/jest/test-helpers';
|
||||
import rootReducer from 'soapbox/reducers';
|
||||
|
||||
import { expandBlocks, fetchBlocks } from '../blocks';
|
||||
|
||||
const account = {
|
||||
acct: 'twoods',
|
||||
display_name: 'Tiger Woods',
|
||||
id: '22',
|
||||
username: 'twoods',
|
||||
};
|
||||
|
||||
describe('fetchBlocks()', () => {
|
||||
let store;
|
||||
|
||||
describe('if logged out', () => {
|
||||
beforeEach(() => {
|
||||
const state = rootReducer(undefined, {}).set('me', null);
|
||||
store = mockStore(state);
|
||||
});
|
||||
|
||||
it('should do nothing', async() => {
|
||||
await store.dispatch(fetchBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if logged in', () => {
|
||||
beforeEach(() => {
|
||||
const state = rootReducer(undefined, {}).set('me', '1234');
|
||||
store = mockStore(state);
|
||||
});
|
||||
|
||||
describe('with a successful API request', () => {
|
||||
beforeEach(() => {
|
||||
const blocks = require('soapbox/__fixtures__/blocks.json');
|
||||
|
||||
__stub((mock) => {
|
||||
mock.onGet('/api/v1/blocks').reply(200, blocks, {
|
||||
link: '<https://example.com/api/v1/blocks?since_id=1>; rel=\'prev\'',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch blocks from the API', async() => {
|
||||
const expectedActions = [
|
||||
{ type: 'BLOCKS_FETCH_REQUEST' },
|
||||
{ type: 'ACCOUNTS_IMPORT', accounts: [account] },
|
||||
{ type: 'BLOCKS_FETCH_SUCCESS', accounts: [account], next: null },
|
||||
{
|
||||
type: 'RELATIONSHIPS_FETCH_REQUEST',
|
||||
ids: ['22'],
|
||||
skipLoading: true,
|
||||
},
|
||||
];
|
||||
await store.dispatch(fetchBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual(expectedActions);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an unsuccessful API request', () => {
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock.onGet('/api/v1/blocks').networkError();
|
||||
});
|
||||
});
|
||||
|
||||
it('should dispatch failed action', async() => {
|
||||
const expectedActions = [
|
||||
{ type: 'BLOCKS_FETCH_REQUEST' },
|
||||
{ type: 'BLOCKS_FETCH_FAIL', error: new Error('Network Error') },
|
||||
];
|
||||
await store.dispatch(fetchBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual(expectedActions);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('expandBlocks()', () => {
|
||||
let store;
|
||||
|
||||
describe('if logged out', () => {
|
||||
beforeEach(() => {
|
||||
const state = rootReducer(undefined, {}).set('me', null);
|
||||
store = mockStore(state);
|
||||
});
|
||||
|
||||
it('should do nothing', async() => {
|
||||
await store.dispatch(expandBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if logged in', () => {
|
||||
beforeEach(() => {
|
||||
const state = rootReducer(undefined, {}).set('me', '1234');
|
||||
store = mockStore(state);
|
||||
});
|
||||
|
||||
describe('without a url', () => {
|
||||
beforeEach(() => {
|
||||
const state = rootReducer(undefined, {})
|
||||
.set('me', '1234')
|
||||
.set('user_lists', { blocks: { next: null } });
|
||||
store = mockStore(state);
|
||||
});
|
||||
|
||||
it('should do nothing', async() => {
|
||||
await store.dispatch(expandBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a url', () => {
|
||||
beforeEach(() => {
|
||||
const state = rootReducer(undefined, {})
|
||||
.set('me', '1234')
|
||||
.set('user_lists', { blocks: { next: 'example' } });
|
||||
store = mockStore(state);
|
||||
});
|
||||
|
||||
describe('with a successful API request', () => {
|
||||
beforeEach(() => {
|
||||
const blocks = require('soapbox/__fixtures__/blocks.json');
|
||||
|
||||
__stub((mock) => {
|
||||
mock.onGet('example').reply(200, blocks, {
|
||||
link: '<https://example.com/api/v1/blocks?since_id=1>; rel=\'prev\'',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should fetch blocks from the url', async() => {
|
||||
const expectedActions = [
|
||||
{ type: 'BLOCKS_EXPAND_REQUEST' },
|
||||
{ type: 'ACCOUNTS_IMPORT', accounts: [account] },
|
||||
{ type: 'BLOCKS_EXPAND_SUCCESS', accounts: [account], next: null },
|
||||
{
|
||||
type: 'RELATIONSHIPS_FETCH_REQUEST',
|
||||
ids: ['22'],
|
||||
skipLoading: true,
|
||||
},
|
||||
];
|
||||
await store.dispatch(expandBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual(expectedActions);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an unsuccessful API request', () => {
|
||||
beforeEach(() => {
|
||||
__stub((mock) => {
|
||||
mock.onGet('example').networkError();
|
||||
});
|
||||
});
|
||||
|
||||
it('should dispatch failed action', async() => {
|
||||
const expectedActions = [
|
||||
{ type: 'BLOCKS_EXPAND_REQUEST' },
|
||||
{ type: 'BLOCKS_EXPAND_FAIL', error: new Error('Network Error') },
|
||||
];
|
||||
await store.dispatch(expandBlocks());
|
||||
const actions = store.getActions();
|
||||
|
||||
expect(actions).toEqual(expectedActions);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,95 +0,0 @@
|
|||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { getNextLinkName } from 'soapbox/utils/quirks';
|
||||
|
||||
import api, { getLinks } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
|
||||
export const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST';
|
||||
export const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS';
|
||||
export const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL';
|
||||
|
||||
export const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST';
|
||||
export const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS';
|
||||
export const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL';
|
||||
|
||||
export function fetchBlocks() {
|
||||
return (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
dispatch(fetchBlocksRequest());
|
||||
|
||||
api(getState).get('/api/v1/blocks').then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)));
|
||||
}).catch(error => dispatch(fetchBlocksFail(error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchBlocksRequest() {
|
||||
return {
|
||||
type: BLOCKS_FETCH_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchBlocksSuccess(accounts, next) {
|
||||
return {
|
||||
type: BLOCKS_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
export function fetchBlocksFail(error) {
|
||||
return {
|
||||
type: BLOCKS_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandBlocks() {
|
||||
return (dispatch, getState) => {
|
||||
if (!isLoggedIn(getState)) return;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
const url = getState().getIn(['user_lists', 'blocks', 'next']);
|
||||
|
||||
if (url === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch(expandBlocksRequest());
|
||||
|
||||
api(getState).get(url).then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandBlocksSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map(item => item.id)));
|
||||
}).catch(error => dispatch(expandBlocksFail(error)));
|
||||
};
|
||||
}
|
||||
|
||||
export function expandBlocksRequest() {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandBlocksSuccess(accounts, next) {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
export function expandBlocksFail(error) {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
import { AnyAction } from '@reduxjs/toolkit';
|
||||
import { AxiosError } from 'axios';
|
||||
|
||||
import { isLoggedIn } from 'soapbox/utils/auth';
|
||||
import { getNextLinkName } from 'soapbox/utils/quirks';
|
||||
|
||||
import api, { getLinks } from '../api';
|
||||
|
||||
import { fetchRelationships } from './accounts';
|
||||
import { importFetchedAccounts } from './importer';
|
||||
|
||||
const BLOCKS_FETCH_REQUEST = 'BLOCKS_FETCH_REQUEST';
|
||||
const BLOCKS_FETCH_SUCCESS = 'BLOCKS_FETCH_SUCCESS';
|
||||
const BLOCKS_FETCH_FAIL = 'BLOCKS_FETCH_FAIL';
|
||||
|
||||
const BLOCKS_EXPAND_REQUEST = 'BLOCKS_EXPAND_REQUEST';
|
||||
const BLOCKS_EXPAND_SUCCESS = 'BLOCKS_EXPAND_SUCCESS';
|
||||
const BLOCKS_EXPAND_FAIL = 'BLOCKS_EXPAND_FAIL';
|
||||
|
||||
const fetchBlocks = () => (dispatch: React.Dispatch<AnyAction>, getState: any) => {
|
||||
if (!isLoggedIn(getState)) return null;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
dispatch(fetchBlocksRequest());
|
||||
|
||||
return api(getState)
|
||||
.get('/api/v1/blocks')
|
||||
.then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(fetchBlocksSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map((item: any) => item.id)) as any);
|
||||
})
|
||||
.catch(error => dispatch(fetchBlocksFail(error)));
|
||||
};
|
||||
|
||||
function fetchBlocksRequest() {
|
||||
return { type: BLOCKS_FETCH_REQUEST };
|
||||
}
|
||||
|
||||
function fetchBlocksSuccess(accounts: any, next: any) {
|
||||
return {
|
||||
type: BLOCKS_FETCH_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
function fetchBlocksFail(error: AxiosError) {
|
||||
return {
|
||||
type: BLOCKS_FETCH_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
const expandBlocks = () => (dispatch: React.Dispatch<AnyAction>, getState: any) => {
|
||||
if (!isLoggedIn(getState)) return null;
|
||||
const nextLinkName = getNextLinkName(getState);
|
||||
|
||||
const url = getState().getIn(['user_lists', 'blocks', 'next']);
|
||||
|
||||
if (url === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
dispatch(expandBlocksRequest());
|
||||
|
||||
return api(getState)
|
||||
.get(url)
|
||||
.then(response => {
|
||||
const next = getLinks(response).refs.find(link => link.rel === nextLinkName);
|
||||
dispatch(importFetchedAccounts(response.data));
|
||||
dispatch(expandBlocksSuccess(response.data, next ? next.uri : null));
|
||||
dispatch(fetchRelationships(response.data.map((item: any) => item.id)) as any);
|
||||
})
|
||||
.catch(error => dispatch(expandBlocksFail(error)));
|
||||
};
|
||||
|
||||
function expandBlocksRequest() {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_REQUEST,
|
||||
};
|
||||
}
|
||||
|
||||
function expandBlocksSuccess(accounts: any, next: any) {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_SUCCESS,
|
||||
accounts,
|
||||
next,
|
||||
};
|
||||
}
|
||||
|
||||
function expandBlocksFail(error: AxiosError) {
|
||||
return {
|
||||
type: BLOCKS_EXPAND_FAIL,
|
||||
error,
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
fetchBlocks,
|
||||
expandBlocks,
|
||||
BLOCKS_FETCH_REQUEST,
|
||||
BLOCKS_FETCH_SUCCESS,
|
||||
BLOCKS_FETCH_FAIL,
|
||||
BLOCKS_EXPAND_REQUEST,
|
||||
BLOCKS_EXPAND_SUCCESS,
|
||||
BLOCKS_EXPAND_FAIL,
|
||||
};
|
Ładowanie…
Reference in New Issue