| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- /**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
- import fetchMock from 'fetch-mock';
- import { JsonValue, SupersetClientClass } from '@superset-ui/core';
- import { makeApi, SupersetApiError } from '../../../../src/query';
- import setupClientForTest from '../setupClientForTest';
- describe('makeApi()', () => {
- beforeAll(() => setupClientForTest());
- afterEach(() => fetchMock.restore());
- it('should expose method and endpoint', () => {
- const api = makeApi({
- method: 'GET',
- endpoint: '/test',
- });
- expect(api.method).toEqual('GET');
- expect(api.endpoint).toEqual('/test');
- expect(api.requestType).toEqual('search');
- });
- it('should allow custom path', async () => {
- expect.assertions(2);
- const api = makeApi({
- method: 'GET',
- endpoint: '/test-custom-client',
- });
- const client = new SupersetClientClass({ appRoot: '/foo' });
- const mockResponse = { yes: 'ok' };
- const mockRequest = jest.fn(() =>
- Promise.resolve(
- new Response(JSON.stringify(mockResponse), {
- headers: { 'Content-Type': 'application/json' },
- }),
- ),
- );
- Object.assign(client, {
- request: mockRequest,
- });
- const result = await api(null, { client });
- expect(result).toEqual(mockResponse);
- expect(mockRequest).toHaveBeenCalledTimes(1);
- });
- it('should obtain json response by default', async () => {
- expect.assertions(1);
- const api = makeApi({
- method: 'GET',
- endpoint: '/test',
- });
- fetchMock.get('glob:*/test', { yes: 'ok' });
- expect(await api({})).toEqual({ yes: 'ok' });
- });
- it('should allow custom parseResponse', async () => {
- expect.assertions(2);
- const responseJson = { items: [1, 2, 3] };
- fetchMock.post('glob:*/test', responseJson);
- const api = makeApi({
- method: 'POST',
- endpoint: '/test',
- processResponse: (json: typeof responseJson) =>
- json.items.reduce((a: number, b: number) => a + b),
- });
- expect(api.method).toEqual('POST');
- expect(await api({})).toBe(6);
- });
- it('should post FormData when requestType=form', async () => {
- expect.assertions(3);
- const api = makeApi({
- method: 'POST',
- endpoint: '/test-formdata',
- requestType: 'form',
- });
- fetchMock.post('glob:*/test-formdata', { test: 'ok' });
- expect(await api({ request: 'test' })).toEqual({ test: 'ok' });
- const expected = new FormData();
- expected.append('request', JSON.stringify('test'));
- const received = fetchMock.lastOptions()?.body as FormData;
- expect(received).toBeInstanceOf(FormData);
- expect(received.get('request')).toEqual(expected.get('request'));
- });
- it('should use searchParams for method=GET (`requestType=search` implied)', async () => {
- expect.assertions(1);
- const api = makeApi({
- method: 'GET',
- endpoint: '/test-get-search',
- });
- fetchMock.get('glob:*/test-get-search*', { search: 'get' });
- await api({ p1: 1, p2: 2, p3: [1, 2] });
- expect(fetchMock.lastUrl()).toContain(
- '/test-get-search?p1=1&p2=2&p3=1%2C2',
- );
- });
- it('should serialize rison for method=GET, requestType=rison', async () => {
- expect.assertions(1);
- const api = makeApi({
- method: 'GET',
- endpoint: '/test-post-search',
- requestType: 'rison',
- });
- fetchMock.get('glob:*/test-post-search*', { rison: 'get' });
- await api({ p1: 1, p3: [1, 2] });
- expect(fetchMock.lastUrl()).toContain(
- '/test-post-search?q=(p1:1,p3:!(1,2))',
- );
- });
- it('should use searchParams for method=POST, requestType=search', async () => {
- expect.assertions(1);
- const api = makeApi({
- method: 'POST',
- endpoint: '/test-post-search',
- requestType: 'search',
- });
- fetchMock.post('glob:*/test-post-search*', { search: 'post' });
- await api({ p1: 1, p3: [1, 2] });
- expect(fetchMock.lastUrl()).toContain('/test-post-search?p1=1&p3=1%2C2');
- });
- it('should throw when requestType is invalid', () => {
- expect(() => {
- makeApi({
- method: 'POST',
- endpoint: '/test-formdata',
- // @ts-ignore
- requestType: 'text',
- });
- }).toThrow('Invalid request payload type');
- });
- it('should handle errors', async () => {
- expect.assertions(1);
- const api = makeApi({
- method: 'POST',
- endpoint: '/test-formdata',
- requestType: 'form',
- });
- let error;
- fetchMock.post('glob:*/test-formdata', { test: 'ok' });
- try {
- await api('<This is an invalid JSON string>');
- } catch (err) {
- error = err;
- } finally {
- expect((error as SupersetApiError).message).toContain('Invalid payload');
- }
- });
- it('should handle error on 200 response', async () => {
- expect.assertions(1);
- const api = makeApi({
- method: 'POST',
- endpoint: '/test-200-error',
- requestType: 'json',
- });
- fetchMock.post('glob:*/test-200-error', { error: 'not ok' });
- let error;
- try {
- await api({});
- } catch (err) {
- error = err;
- } finally {
- expect((error as SupersetApiError).message).toContain('not ok');
- }
- });
- it('should parse text response when responseType=text', async () => {
- expect.assertions(1);
- const api = makeApi<JsonValue, string, 'text'>({
- method: 'PUT',
- endpoint: '/test-parse-text',
- requestType: 'form',
- responseType: 'text',
- processResponse: text => `${text}?`,
- });
- fetchMock.put('glob:*/test-parse-text', 'ok');
- const result = await api({ field1: 11 });
- expect(result).toBe('ok?');
- });
- it('should return raw response when responseType=raw', async () => {
- expect.assertions(2);
- const api = makeApi<JsonValue, number, 'raw'>({
- method: 'DELETE',
- endpoint: '/test-raw-response',
- responseType: 'raw',
- processResponse: response => response.status,
- });
- fetchMock.delete('glob:*/test-raw-response?*', 'ok');
- const result = await api({ field1: 11 }, {});
- expect(result).toEqual(200);
- expect(fetchMock.lastUrl()).toContain('/test-raw-response?field1=11');
- });
- });
|