Update ServersImporter so that it takes into consideration forwardCredentials

This commit is contained in:
Alejandro Celaya 2025-04-20 13:06:09 +02:00
parent 4895cbb9dc
commit d65eafd37f
3 changed files with 56 additions and 28 deletions

View File

@ -54,3 +54,22 @@ export const serializeServer = ({ name, url, apiKey, forwardCredentials }: Serve
apiKey,
forwardCredentials: forwardCredentials ? 'true' : 'false',
});
const validateServerData = (server: any): server is ServerData =>
typeof server.url === 'string' && typeof server.apiKey === 'string' && typeof server.name === 'string';
/**
* Provided a record, it picks the right properties to build a ServerData object.
* @throws Error If any of the required ServerData properties is missing.
*/
export const deserializeServer = (potentialServer: Record<string, unknown>): ServerData => {
const { forwardCredentials, ...serverData } = potentialServer;
if (!validateServerData(serverData)) {
throw new Error('Server is missing required "url", "apiKey" and/or "name" properties');
}
return {
...serverData,
forwardCredentials: forwardCredentials === 'true',
};
};

View File

@ -1,14 +1,20 @@
import type { CsvToJson } from '../../utils/helpers/csvjson';
import type { ServerData } from '../data';
import { deserializeServer } from '../data';
const validateServer = (server: any): server is ServerData =>
typeof server.url === 'string' && typeof server.apiKey === 'string' && typeof server.name === 'string';
const validateServers = (servers: any): servers is ServerData[] =>
Array.isArray(servers) && servers.every(validateServer);
const validateAndDeserializeServers = (servers: unknown): ServerData[] => {
if (!Array.isArray(servers)) {
throw new Error('Provided file does not have the right format.');
}
return servers.map(deserializeServer);
};
export class ServersImporter {
public constructor(private readonly csvToJson: CsvToJson) {}
readonly #csvToJson: CsvToJson;
public constructor(csvToJson: CsvToJson) {
this.#csvToJson = csvToJson;
}
public async importServersFromFile(file: File | null | undefined): Promise<ServerData[]> {
if (!file) {
@ -16,12 +22,8 @@ export class ServersImporter {
}
const content = await file.text();
const servers = await this.csvToJson(content);
const servers = await this.#csvToJson(content);
if (!validateServers(servers)) {
throw new Error('Provided file does not have the right format.');
}
return servers;
return validateAndDeserializeServers(servers);
}
}

View File

@ -1,5 +1,5 @@
import { fromPartial } from '@total-typescript/shoehorn';
import type { RegularServer } from '../../../src/servers/data';
import type { RegularServer, ServerData } from '../../../src/servers/data';
import { ServersImporter } from '../../../src/servers/services/ServersImporter';
describe('ServersImporter', () => {
@ -25,20 +25,24 @@ describe('ServersImporter', () => {
});
it.each([
[{}],
[undefined],
[[{ foo: 'bar' }]],
[
[
{ parsedObject: {}, expectedError: 'Provided file does not have the right format.' },
{ parsedObject: undefined, expectedError: 'Provided file does not have the right format.' },
{
parsedObject: [{ foo: 'bar' }],
expectedError: 'Server is missing required "url", "apiKey" and/or "name" properties',
},
{
parsedObject: [
{
url: 1,
apiKey: 1,
name: 1,
},
],
],
[
[
expectedError: 'Server is missing required "url", "apiKey" and/or "name" properties',
},
{
parsedObject: [
{
url: 'foo',
apiKey: 'foo',
@ -46,26 +50,29 @@ describe('ServersImporter', () => {
},
{ bar: 'foo' },
],
],
])('rejects with error if provided file does not parse to valid list of servers', async (parsedObject) => {
expectedError: 'Server is missing required "url", "apiKey" and/or "name" properties',
},
])('rejects with error if provided file does not parse to valid list of servers', async ({
parsedObject,
expectedError,
}) => {
csvjsonMock.mockResolvedValue(parsedObject);
await expect(importer.importServersFromFile(fileMock())).rejects.toEqual(
new Error('Provided file does not have the right format.'),
);
await expect(importer.importServersFromFile(fileMock())).rejects.toEqual(new Error(expectedError));
});
it('reads file when a CSV containing valid servers is provided', async () => {
const expectedServers = [
const expectedServers: Required<ServerData>[] = [
{
url: 'foo',
apiKey: 'foo',
name: 'foo',
forwardCredentials: false,
},
{
url: 'bar',
apiKey: 'bar',
name: 'bar',
forwardCredentials: false,
},
];