Skip to content

Commit

Permalink
chore(tests): Add tests for admin APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
neet committed Apr 8, 2023
1 parent 75a310b commit 7efa306
Show file tree
Hide file tree
Showing 32 changed files with 523 additions and 56 deletions.
2 changes: 1 addition & 1 deletion jest.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ module.exports = {
setupFilesAfterEnv: ['<rootDir>/test-utils/jest-setup-after-env.ts'],
},
],
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.spec.ts'],
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.spec.ts', '!**/__mocks__/**'],
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Http } from './http';
import type { Http } from '../http/http';

export const httpRequest = jest.fn();
export const httpGet = jest.fn();
Expand Down
3 changes: 3 additions & 0 deletions src/__mocks__/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './http-mock-impl';
export * from './ws-mock-impl';
export * from './logger-mock-impl';
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { BaseLogger } from './base-logger';
import { BaseLogger } from '../logger';

export const log = jest.fn();

Expand Down
2 changes: 1 addition & 1 deletion src/ws/ws-mock-impl.ts → src/__mocks__/ws-mock-impl.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import EventEmitter from 'eventemitter3';

import type { EventTypeMap, Ws, WsEvents } from './ws';
import type { EventTypeMap, Ws, WsEvents } from '../ws';

export const wsDisconnect = jest.fn();
export const wsOn = jest.fn();
Expand Down
118 changes: 118 additions & 0 deletions src/errors/factory.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { createHttpError } from './factory';
import { MastoHttpConflictError } from './masto-http-conflict-error';
import { MastoHttpForbiddenError } from './masto-http-forbidden-error';
import { MastoHttpGoneError } from './masto-http-gone-error';
import { MastoHttpNotFoundError } from './masto-http-not-found-error';
import { MastoHttpRateLimitError } from './masto-http-rate-limit-error';
import { MastoHttpUnauthorizedError } from './masto-http-unauthorized-error';
import { MastoHttpUnexpectedError } from './masto-http-unexpected-error';
import { MastoHttpUnprocessableEntityError } from './masto-http-unprocessable-entity-error';

describe('HTTP error factory', () => {
it('creates unauthorized error', () => {
const cause = {};
const error = createHttpError({
statusCode: 401,
message: 'Unauthorized',
cause,
});

expect(error).toBeInstanceOf(MastoHttpUnauthorizedError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Unauthorized');
});

it('creates forbidden error', () => {
const cause = {};
const error = createHttpError({
statusCode: 403,
message: 'Forbidden',
cause,
});

expect(error).toBeInstanceOf(MastoHttpForbiddenError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Forbidden');
});

it('creates not found error', () => {
const cause = {};
const error = createHttpError({
statusCode: 404,
message: 'Not Found',
cause,
});

expect(error).toBeInstanceOf(MastoHttpNotFoundError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Not Found');
});

it('creates conflict error', () => {
const cause = {};
const error = createHttpError({
statusCode: 409,
message: 'Conflict',
cause,
});

expect(error).toBeInstanceOf(MastoHttpConflictError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Conflict');
});

it('creates gone error', () => {
const cause = {};
const error = createHttpError({
statusCode: 410,
message: 'Gone',
cause,
});

expect(error).toBeInstanceOf(MastoHttpGoneError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Gone');
});

it('creates unprocessable entity error', () => {
const cause = {};
const error = createHttpError({
statusCode: 422,
message: 'Unprocessable Entity',
cause,
});

expect(error).toBeInstanceOf(MastoHttpUnprocessableEntityError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Unprocessable Entity');
});

it('creates rate limit error', () => {
const cause = {};
const error = createHttpError({
statusCode: 429,
message: 'Rate Limit Exceeded',
cause,
limit: 100,
remaining: 0,
reset: '2021-01-01T00:00:00.000Z',
});

expect(error).toBeInstanceOf(MastoHttpRateLimitError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Rate Limit Exceeded');
});

it('creates unexpected error', () => {
const cause = {};
const error = createHttpError({
statusCode: 500,
message: 'Internal Server Error',
cause,
});

expect(error).toBeInstanceOf(MastoHttpUnexpectedError);
expect(error.cause).toBe(cause);
expect(error.message).toBe('Internal Server Error');
});
});
6 changes: 3 additions & 3 deletions src/errors/masto-http-rate-limit-error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ export class MastoHttpRateLimitError extends MastoHttpError {
super(message, 429, props);
Object.setPrototypeOf(this, MastoHttpRateLimitError.prototype);

this.limit = props?.limit;
this.remaining = props?.remaining;
this.reset = props?.reset;
this.limit = props.limit;
this.remaining = props.remaining;
this.reset = props.reset;
}
}
8 changes: 8 additions & 0 deletions src/errors/masto-unexpected-error.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { MastoUnexpectedError } from './masto-unexpected-error';

it('constructs', () => {
const error = new MastoUnexpectedError('foo');
expect(error.message).toBe('foo');
expect(error.name).toBe('MastoUnexpectedError');
expect(error.stack).toBeDefined();
});
8 changes: 8 additions & 0 deletions src/errors/masto-version-error.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { MastoVersionError } from './masto-version-error';

it('constructs', () => {
const error = new MastoVersionError('foo');
expect(error.message).toBe('foo');
expect(error.name).toBe('MastoVersionError');
expect(error.stack).toBeDefined();
});
2 changes: 1 addition & 1 deletion src/logger/base-logger.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable unicorn/no-useless-undefined */
import { log, LoggerMockImpl } from '../__mocks__';
import { LogLevel } from './log-level';
import { log, LoggerMockImpl } from './logger-mock-impl';

describe('debug', () => {
const level = LogLevel.from('debug');
Expand Down
16 changes: 13 additions & 3 deletions src/mastodon/v1/entities/admin/report.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import type { Account, Status } from '..';
import type { Account, Rule, Status } from '..';

export type ReportCategory = 'spam' | 'violation' | 'other';

/**
* Admin-level information about a filed report.
Expand All @@ -8,9 +10,15 @@ export interface Report {
/** The ID of the report in the database. */
id: string;
/** The action taken to resolve this report. */
actionTaken: string;
actionTaken: boolean;
/** When an action was taken, if this report is currently resolved. */
actionTakenAt?: string | null;
/** The category under which the report is classified */
category: ReportCategory;
/** An optional reason for reporting. */
comment: string;
/** Whether a report was forwarded to a remote instance. */
forwarded: boolean;
/** The time the report was filed. */
createdAt: string;
/** The time of last action on this report. */
Expand All @@ -20,9 +28,11 @@ export interface Report {
/** The account being reported. */
targetAccount: Account;
/** The account of the moderator assigned to this report. */
assignedAccount: Account;
assignedAccount?: Account | null;
/** The action taken by the moderator who handled the report. */
actionTakenByAccount: Account;
/** Statuses attached to the report, for context. */
statuses: Status[];
/** Rules attached to the report, for context. */
rules: Rule[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,13 +73,15 @@ export class CanonicalEmailBlockRepository
* Canonicalize and hash an email address.
* @param params Parameters
* @return Array of CanonicalEmailBlock
* @see https://docs.joinmastodon.org/methods/admin/canonical_email_blocks
* @see https://docs.joinmastodon.org/methods/admin/canonical_email_blocks/#test
*/
@version({ since: '4.0.0' })
test(
params: TestCanonicalEmailBlockParams,
): Promise<Admin.CanonicalEmailBlock> {
return this.http.post('/api/v1/admin/canonical_email_blocks/test', params);
): Promise<Admin.CanonicalEmailBlock[]> {
return this.http.post('/api/v1/admin/canonical_email_blocks/test', params, {
headers: { 'Content-Type': 'multipart/form-data' },
});
}

/**
Expand All @@ -92,7 +94,9 @@ export class CanonicalEmailBlockRepository
create(
params: CreateCanonicalEmailBlockParams,
): Promise<Admin.CanonicalEmailBlock> {
return this.http.post('/api/v1/admin/canonical_email_blocks', params);
return this.http.post('/api/v1/admin/canonical_email_blocks', params, {
headers: { 'Content-Type': 'multipart/form-data' },
});
}

/**
Expand Down
6 changes: 2 additions & 4 deletions src/mastodon/v1/repositories/admin/dimension-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export interface FetchDimensionParams {
*
* - `instance_languages` = Most-used languages from a remote server
*/
readonly keys: DimensionKey[];
readonly keys: readonly DimensionKey[];
/** String (ISO 8601 Datetime). The start date for the time period. If a time is provided, it will be ignored. */
readonly startAt?: string | null;
/** String (ISO 8601 Datetime). The end date for the time period. If a time is provided, it will be ignored. */
Expand Down Expand Up @@ -63,8 +63,6 @@ export class DimensionRepository {
* @see https://docs.joinmastodon.org/methods/admin/dimensions/#get
*/
fetch(params: FetchDimensionParams): Promise<Admin.Dimension[]> {
return this.http.post('/api/v1/admin/dimensions', params, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return this.http.post('/api/v1/admin/dimensions', params);
}
}
18 changes: 7 additions & 11 deletions src/mastodon/v1/repositories/admin/domain-allow-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,9 @@ import { version } from '../../../../decorators';
import type { Http } from '../../../../http';
import type { Logger } from '../../../../logger';
import { Paginator } from '../../../../paginator';
import type { Repository } from '../../../repository';
import type { DefaultPaginationParams, Repository } from '../../../repository';
import type { Admin } from '../../entities';

export type ListDomainAllowsParams = {
readonly limit?: number;
};

export interface CreateDomainAllowParams {
readonly domain: string;
}
Expand All @@ -21,7 +17,7 @@ export class DomainAllowRepository
CreateDomainAllowParams,
never,
never,
ListDomainAllowsParams
DefaultPaginationParams
>
{
constructor(
Expand All @@ -34,20 +30,20 @@ export class DomainAllowRepository
* Show information about all allowed domains
* @param params Parameters
* @return Array of DomainAllow
* @see https://docs.joinmastodon.org/methods/admin/
* @see https://docs.joinmastodon.org/methods/admin/domain_allows/#get
*/
@version({ since: '4.0.0' })
list(
params?: ListDomainAllowsParams,
): Paginator<Admin.DomainAllow[], ListDomainAllowsParams> {
params?: DefaultPaginationParams,
): Paginator<Admin.DomainAllow[], DefaultPaginationParams> {
return new Paginator(this.http, '/api/v1/admin/domain_allows', params);
}

/**
* Show information about a single allowed domain
* @param id id of the domain
* @return DomainAllow
* @see https://docs.joinmastodon.org/methods/admin/
* @see https://docs.joinmastodon.org/methods/admin/domain_allows/#get-one
*/
@version({ since: '4.0.0' })
fetch(id: string): Promise<Admin.DomainAllow> {
Expand All @@ -59,7 +55,7 @@ export class DomainAllowRepository
* to be used when the instance is in allow-list federation mode.
* @param params parameters
* @return DomainAllow
* @see https://docs.joinmastodon.org/methods/admin/
* @see https://docs.joinmastodon.org/methods/admin/domain_allows/#get-one
*/
@version({ since: '4.0.0' })
create(params: CreateDomainAllowParams): Promise<Admin.DomainAllow> {
Expand Down
8 changes: 4 additions & 4 deletions src/mastodon/v1/repositories/admin/ip-block-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export class IpBlockRepository
* Add an IP address range to the list of IP blocks.
* @param params Parameters
* @return object of Ip Block
* @see https://docs.joinmastodon.org/methods/admin/
* @see https://docs.joinmastodon.org/methods/admin/ip_blocks/#create
*/
@version({ since: '4.0.0' })
create(params: CreateIpBlockParams): Promise<Admin.IpBlock> {
Expand All @@ -89,11 +89,11 @@ export class IpBlockRepository
* Change parameters for an existing IP block.
* @param params Parameters
* @return object of Ip Block
* @see https://docs.joinmastodon.org/methods/admin/
* @see https://docs.joinmastodon.org/methods/admin/ip_blocks/#update
*/
@version({ since: '4.0.0' })
update(params: UpdateIpBlockParams): Promise<Admin.IpBlock> {
return this.http.put('/api/v1/admin/ip_blocks', params);
update(id: string, params: UpdateIpBlockParams): Promise<Admin.IpBlock> {
return this.http.put(`/api/v1/admin/ip_blocks/${id}`, params);
}

/**
Expand Down
4 changes: 1 addition & 3 deletions src/mastodon/v1/repositories/admin/measure-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,6 @@ export class MeasureRepository {
*/
@version({ since: '3.5.0' })
fetch(params: FetchMeasureParams): Promise<Admin.Measure[]> {
return this.http.post('/api/v1/admin/measures', params, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return this.http.post('/api/v1/admin/measures', params);
}
}
4 changes: 1 addition & 3 deletions src/mastodon/v1/repositories/admin/retention-repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ export class RetentionRepository {
* @see https://docs.joinmastodon.org/methods/admin/retention/#create
*/
create(params: CreateRetentionParams): Promise<Admin.Cohort[]> {
return this.http.get('/api/v1/admin/retention', params, {
headers: { 'Content-Type': 'multipart/form-data' },
});
return this.http.post('/api/v1/admin/retention', params);
}
}
2 changes: 1 addition & 1 deletion src/paginator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Headers } from '@mastojs/ponyfills';

import { HttpMockImpl } from './http/http-mock-impl';
import { HttpMockImpl } from './__mocks__';
import { Paginator } from './paginator';

describe('Paginator', () => {
Expand Down
Loading

0 comments on commit 7efa306

Please sign in to comment.