chore: add eslint package standard-with-typescript and apply rules

This commit is contained in:
Sándor Levcsák 2020-11-11 02:23:42 +02:00 committed by plumrx
parent bdeba68aa8
commit f114698e8d
36 changed files with 237 additions and 247 deletions

29
.eslintrc Normal file
View File

@ -0,0 +1,29 @@
{
"root": true,
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "@typescript-eslint/parser",
"project": "./tsconfig.json",
"sourceType": "module",
"extraFileExtensions": [
".vue",
".d.ts"
]
},
"extends": [
"standard",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"standard-with-typescript",
"plugin:vue/vue3-recommended"
],
"rules": {
"no-undef": "off",
"comma-dangle": [
"warn",
"always-multiline"
],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/promise-function-async": "off"
}
}

16
cypress/.eslintrc Normal file
View File

@ -0,0 +1,16 @@
{
"root": true,
"env": {
"cypress/globals": true
},
"extends": [
"standard",
"plugin:cypress/recommended"
],
"rules": {
"comma-dangle": [
"warn",
"always-multiline"
]
}
}

View File

@ -1,5 +1,3 @@
/* eslint-disable @typescript-eslint/no-unused-vars */
/// <reference types="cypress" />
// ***********************************************************
// This example plugins/index.js can be used to load plugins

View File

@ -6,7 +6,7 @@
"dev": "vite",
"build": "vite build",
"check-ts-errors": "yarn tsc && yarn vti diagnostics",
"lint": "eslint \"{src,cypress/integration}/**/*.{js,ts,vue}\"",
"lint": "eslint \"{src,cypress}/**/*.{js,ts,vue}\"",
"test:unit": "jest --coverage",
"test:e2e": "cypress run",
"test": "yarn check-ts-errors && yarn lint && yarn test:unit && yarn test:e2e"
@ -26,19 +26,20 @@
"@types/dompurify": "^2.0.4",
"@types/jest": "^24.9.1",
"@types/marked": "^1.1.0",
"@typescript-eslint/eslint-plugin": "^4.6.1",
"@typescript-eslint/parser": "^4.6.1",
"@typescript-eslint/eslint-plugin": "^4.7.0",
"@typescript-eslint/parser": "^4.7.0",
"@vue/compiler-sfc": "^3.0.2",
"@vue/test-utils": "^2.0.0-beta.8",
"babel-jest": "^24.9.0",
"cypress": "^5.3.0",
"eslint": "^7.12.1",
"eslint": "^7.13.0",
"eslint-config-standard": "^16.0.1",
"eslint-config-standard-with-typescript": "^19.0.1",
"eslint-plugin-cypress": "^2.11.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.2.1",
"eslint-plugin-standard": "^4.0.2",
"eslint-plugin-standard": "^4.1.0",
"eslint-plugin-vue": "^7.1.0",
"husky": "^4.3.0",
"jest": "^24.9.0",
@ -60,30 +61,6 @@
"src/**/*.{ts,vue}": "eslint --fix",
"cypress/**/*.js": "eslint --fix"
},
"eslintConfig": {
"parser": "vue-eslint-parser",
"parserOptions": {
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"sourceType": "module"
},
"extends": [
"standard",
"plugin:cypress/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended",
"plugin:vue/vue3-recommended"
],
"rules": {
"no-undef": "off",
"comma-dangle": [
"warn",
"always-multiline"
]
}
},
"jest": {
"preset": "ts-jest",
"globals": {

View File

@ -59,9 +59,9 @@ export function useArticles () {
const { active: articlesDownloading, run: runWrappedFetchArticles } = createAsyncProcess(fetchArticles)
watch(metaChanged, () => {
watch(metaChanged, async () => {
if (page.value !== 1) changePage(1)
else runWrappedFetchArticles()
else await runWrappedFetchArticles()
})
watch(page, runWrappedFetchArticles)

View File

@ -19,7 +19,7 @@ export function useFollow ({ username, following, onUpdate }: UseFollowProps) {
async function toggleFollow () {
let response: Either<AuthorizationError, Profile>
if (following.value === true) {
if (following.value) {
response = await deleteFollowProfile(username.value)
} else {
response = await postFollowProfile(username.value)

View File

@ -16,7 +16,7 @@ export function useProfile ({ username }: UseProfileProps) {
updateProfile(profileData)
}
async function updateProfile (profileData: Profile | null) {
function updateProfile (profileData: Profile | null) {
profile.value = profileData
}

View File

@ -1,3 +1,4 @@
export const CONFIG = {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
API_HOST: import.meta.env.VITE_API_HOST || '',
}

View File

@ -3,5 +3,5 @@ import storage from '../utils/storage'
export default function (): void {
const token = storage.get<User>('user')?.token
if (token) request.setAuthorizationHeader(token)
if (token !== undefined) request.setAuthorizationHeader(token)
}

View File

@ -2,16 +2,16 @@ import { createRouter, createWebHashHistory, RouteParams } from 'vue-router'
import Home from './pages/Home.vue'
export type AppRouteNames = 'global-feed'
| 'my-feed'
| 'tag'
| 'article'
| 'create-article'
| 'edit-article'
| 'login'
| 'register'
| 'profile'
| 'profile-favorites'
| 'settings'
| 'my-feed'
| 'tag'
| 'article'
| 'create-article'
| 'edit-article'
| 'login'
| 'register'
| 'profile'
| 'profile-favorites'
| 'settings'
export const router = createRouter({
history: createWebHashHistory(),
@ -75,6 +75,6 @@ export const router = createRouter({
})
export function routerPush (name: AppRouteNames, params?: RouteParams): ReturnType<typeof router.push> {
if (params) return router.push({ name, params })
if (params !== undefined) return router.push({ name, params })
else return router.push({ name })
}

View File

@ -1,5 +1,5 @@
import { request } from '../index'
export async function deleteArticle (slug: string): Promise<void> {
export function deleteArticle (slug: string): Promise<void> {
return request.delete(`/articles/${slug}`)
}

View File

@ -1,5 +1,5 @@
import { request } from '../index'
export async function getArticle (slug: string): Promise<Article> {
export function getArticle (slug: string): Promise<Article> {
return request.get<ArticleResponse>(`/articles/${slug}`).then(res => res.article)
}

View File

@ -1,26 +1,26 @@
import { limit, request } from '../index'
export async function getArticles (page = 1): Promise<ArticlesResponse> {
export function getArticles (page = 1): Promise<ArticlesResponse> {
const params = { limit, offset: (page - 1) * limit }
return request.get<ArticlesResponse>('/articles', { params })
}
export async function getFavoritedArticles (username: string, page = 1): Promise<ArticlesResponse> {
export function getFavoritedArticles (username: string, page = 1): Promise<ArticlesResponse> {
const params = { limit, offset: (page - 1) * limit, favorited: username }
return request.get<ArticlesResponse>('/articles', { params })
}
export async function getProfileArticles (username: string, page = 1): Promise<ArticlesResponse> {
export function getProfileArticles (username: string, page = 1): Promise<ArticlesResponse> {
const params = { limit, offset: (page - 1) * limit, author: username }
return request.get<ArticlesResponse>('/articles', { params })
}
export async function getFeeds (page = 1): Promise<ArticlesResponse> {
export function getFeeds (page = 1): Promise<ArticlesResponse> {
const params = { limit, offset: (page - 1) * limit }
return request.get<ArticlesResponse>('/articles/feed', { params })
}
export async function getArticlesByTag (tagName: string, page = 1): Promise<ArticlesResponse> {
export function getArticlesByTag (tagName: string, page = 1): Promise<ArticlesResponse> {
const params = { tag: tagName, limit, offset: (page - 1) * limit }
return request.get<ArticlesResponse>('/articles', { params })
}

View File

@ -1,18 +1,18 @@
import { request } from '../index'
interface PostArticleForm {
title: string;
description: string;
body: string;
tagList: string[];
title: string
description: string
body: string
tagList: string[]
}
export async function postArticle (form: PostArticleForm): Promise<Article> {
export function postArticle (form: PostArticleForm): Promise<Article> {
return request.post<ArticleResponse>('/articles', { article: form })
.then(res => res.article)
}
export async function putArticle (slug: string, form: PostArticleForm): Promise<Article> {
export function putArticle (slug: string, form: PostArticleForm): Promise<Article> {
return request.put<ArticleResponse>(`/articles/${slug}`, { article: form })
.then(res => res.article)
}

View File

@ -6,8 +6,8 @@ import { mapValidationResponse } from '../../utils/map-checkable-response'
import { Either, fail, success } from '../../utils/either'
export interface PostLoginForm {
email: string;
password: string;
email: string
password: string
}
export type PostLoginErrors = Partial<Record<keyof PostLoginForm, string[]>>

View File

@ -6,9 +6,9 @@ import { mapValidationResponse } from '../../utils/map-checkable-response'
import { Either, fail, success } from '../../utils/either'
export interface PostRegisterForm {
email: string;
password: string;
username: string;
email: string
password: string
username: string
}
export type PostRegisterErrors = Partial<Record<keyof PostRegisterForm, string[]>>

View File

@ -1,5 +1,5 @@
import { request } from '../index'
export async function getCommentsByArticle (slug: string): Promise<ArticleComment[]> {
export function getCommentsByArticle (slug: string): Promise<ArticleComment[]> {
return request.get<CommentsResponse>(`/articles/${slug}/comments`).then(res => res.comments)
}

View File

@ -1,10 +1,10 @@
import { request } from '../index'
export async function deleteComment (slug: string, commentId: number): Promise<Record<string, unknown>> {
export function deleteComment (slug: string, commentId: number): Promise<Record<string, unknown>> {
return request.delete(`/articles/${slug}/comments/${commentId}`)
}
export async function postComment (slug: string, body: string): Promise<ArticleComment> {
export function postComment (slug: string, body: string): Promise<ArticleComment> {
return request.post<CommentResponse>(`/articles/${slug}/comments`, { comment: { body } })
.then(res => res.comment)
}

View File

@ -1,5 +1,5 @@
import { request } from '../index'
export async function getProfile (username: string): Promise<Profile> {
export function getProfile (username: string): Promise<Profile> {
return request.get<ProfileResponse>(`/profiles/${username}`).then(res => res.profile)
}

View File

@ -1,13 +1,13 @@
import { request } from '../index'
export interface PutProfileForm {
username?: string;
bio?: string;
image?: string;
email?: string;
password?: string;
username?: string
bio?: string
image?: string
email?: string
password?: string
}
export async function putProfile (form: PutProfileForm): Promise<User> {
export function putProfile (form: PutProfileForm): Promise<User> {
return request.put<UserResponse>('/user', form).then(res => res.user)
}

View File

@ -1,5 +1,5 @@
import { request } from '../index'
export async function getAllTags (): Promise<string[]> {
export function getAllTags (): Promise<string[]> {
return request.get<TagsResponse>('/tags').then(res => res.tags)
}

8
src/shimes-vue.d.ts vendored
View File

@ -5,8 +5,8 @@ declare module '*.vue' {
export default Component
}
interface ImportMeta {
env: {
VITE_API_HOST: string
}
interface ImportMeta {
env: {
VITE_API_HOST: string
}
}

View File

@ -23,7 +23,7 @@ export const checkAuthorization = (user: ComputedRef<User | null>): user is Comp
}
export const updateUser = mutation<User | null>('updateUser', (state, userData) => {
if (!userData) {
if (userData === undefined || userData === null) {
storage.remove('user')
request.deleteAuthorizationHeader()
state.user = null

View File

@ -1,12 +1,12 @@
declare interface Article {
title: string;
slug: string;
body: string;
createdAt: string;
updatedAt: string;
tagList: string[];
description: string;
author: Profile;
favorited: boolean;
favoritesCount: number;
title: string
slug: string
body: string
createdAt: string
updatedAt: string
tagList: string[]
description: string
author: Profile
favorited: boolean
favoritesCount: number
}

View File

@ -1,7 +1,7 @@
declare interface ArticleComment {
id: number;
createdAt: string;
updatedAt: string;
body: string;
author: Profile;
id: number
createdAt: string
updatedAt: string
body: string
author: Profile
}

View File

@ -1,28 +1,28 @@
declare interface UserResponse {
user: User;
user: User
}
declare interface TagsResponse {
tags: string[];
tags: string[]
}
declare interface ProfileResponse {
profile: Profile;
profile: Profile
}
declare interface ArticleResponse {
article: Article;
article: Article
}
declare interface ArticlesResponse {
articles: Article[];
articlesCount: number;
articles: Article[]
articlesCount: number
}
declare interface CommentResponse {
comment: ArticleComment;
comment: ArticleComment
}
declare interface CommentsResponse {
comments: ArticleComment[];
comments: ArticleComment[]
}

20
src/types/user.d.ts vendored
View File

@ -1,15 +1,15 @@
declare interface Profile {
username: string;
bio: string;
image: string;
following: boolean;
username: string
bio: string
image: string
following: boolean
}
declare interface User {
id: number;
email: string;
username: string;
bio: string | undefined;
image: string | undefined;
token: string;
id: number
email: string
username: string
bio: string | undefined
image: string | undefined
token: string
}

View File

@ -2,7 +2,7 @@ import { isRef } from 'vue'
import createAsyncProcess from './create-async-process'
describe('# Create async process', function () {
const someProcess = async () => Promise.resolve(null)
const someProcess = () => Promise.resolve(null)
it('should expect active as Vue Ref type', function () {
const { active } = createAsyncProcess(someProcess)

View File

@ -3,7 +3,7 @@ import { Ref, ref } from 'vue'
// eslint-disable-next-line @typescript-eslint/no-explicit-any
interface CreateAsyncProcessReturn<T extends (...args: any[]) => any> {
active: Ref<boolean>
run: (...args : Parameters<T>) => Promise<ReturnType<T>>
run: (...args: Parameters<T>) => Promise<ReturnType<T>>
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any

View File

@ -2,7 +2,7 @@ import { ValidationError, AuthorizationError, NetworkError } from 'src/types/err
import { Either, fail, isEither, success } from './either'
import { mapAuthorizationResponse, mapValidationResponse } from './map-checkable-response'
const createCheckableResponse = (response: Partial<Response>): Either<NetworkError, Partial<Response>> => response.ok
const createCheckableResponse = (response: Partial<Response>): Either<NetworkError, Partial<Response>> => response.ok === true
? success(response)
: fail(new NetworkError(response as Response))

View File

@ -52,7 +52,7 @@ async function triggerMethod<T = unknown> (request: FetchRequest, method: Method
}
}
function forCorrectMethods (task: string, fn: (method: Method) => void): void {
function forCorrectMethods (task: string, fn: (method: Method) => Promise<void>): void {
wrapTests<Method>({
task,
fn,
@ -61,7 +61,7 @@ function forCorrectMethods (task: string, fn: (method: Method) => void): void {
})
}
function forCheckableMethods (task: string, fn: (method: CheckableMethod) => void): void {
function forCheckableMethods (task: string, fn: (method: CheckableMethod) => Promise<void>): void {
wrapTests<CheckableMethod>({
task,
fn,
@ -70,7 +70,7 @@ function forCheckableMethods (task: string, fn: (method: CheckableMethod) => voi
})
}
function forAllMethods (task: string, fn: (method: Method | CheckableMethod) => void): void {
function forAllMethods (task: string, fn: (method: Method | CheckableMethod) => Promise<void>): void {
forCheckableMethods(task, fn)
forCorrectMethods(task, fn)
}
@ -78,7 +78,7 @@ function forAllMethods (task: string, fn: (method: Method | CheckableMethod) =>
forAllMethods('# Should be implemented', async (method) => {
const request = new FetchRequest()
triggerMethod(request, method)
await triggerMethod(request, method)
expect(global.fetch).toBeCalledWith(PATH, expect.objectContaining({
method: method.replace('checkable', '').toUpperCase(),
@ -89,7 +89,7 @@ describe('# Should implement prefix', () => {
forAllMethods('should implement global prefix', async (method) => {
const request = new FetchRequest({ prefix: PREFIX })
triggerMethod(request, method)
await triggerMethod(request, method)
expect(global.fetch).toBeCalledWith(`${PREFIX}${PATH}`, expect.any(Object))
})
@ -97,7 +97,7 @@ describe('# Should implement prefix', () => {
forAllMethods('should implement local prefix', async (method) => {
const request = new FetchRequest()
triggerMethod(request, method, { prefix: SUB_PREFIX })
await triggerMethod(request, method, { prefix: SUB_PREFIX })
expect(global.fetch).toBeCalledWith(`${SUB_PREFIX}${PATH}`, expect.any(Object))
})
@ -105,7 +105,7 @@ describe('# Should implement prefix', () => {
forAllMethods('should implement global + local prefix', async (method) => {
const request = new FetchRequest({ prefix: PREFIX })
triggerMethod(request, method, { prefix: SUB_PREFIX })
await triggerMethod(request, method, { prefix: SUB_PREFIX })
expect(global.fetch).toBeCalledWith(`${SUB_PREFIX}${PATH}`, expect.any(Object))
})
@ -115,7 +115,7 @@ describe('# Should convert query object to query string in request url', () => {
forAllMethods('should implement global query', async (method) => {
const request = new FetchRequest({ params: PARAMS })
triggerMethod(request, method)
await triggerMethod(request, method)
expect(global.fetch).toBeCalledWith(`${PATH}?${params2query(PARAMS)}`, expect.any(Object))
})
@ -123,7 +123,7 @@ describe('# Should convert query object to query string in request url', () => {
forAllMethods('should implement local query', async (method) => {
const request = new FetchRequest()
triggerMethod(request, method, { params: PARAMS })
await triggerMethod(request, method, { params: PARAMS })
expect(global.fetch).toBeCalledWith(`${PATH}?${params2query(PARAMS)}`, expect.any(Object))
})
@ -134,7 +134,7 @@ describe('# Should convert query object to query string in request url', () => {
const expectedOptions = { params: { q1: 'q11', q2: 'q2', q3: 'q3' } }
const request = new FetchRequest(options)
triggerMethod(request, method, localOptions)
await triggerMethod(request, method, localOptions)
expect(global.fetch).toBeCalledWith(`${PATH}?${params2query(expectedOptions.params)}`, expect.any(Object))
})
@ -174,15 +174,15 @@ forCorrectMethods('# Should converted correct response body to json', async func
forCheckableMethods('# Should converted checkable response to Either<NetworkError, DATA_TYPE>', async function (method) {
const DATA = { foo: 'bar' }
type DATA_TYPE = {foo: 'bar'}
interface DATA_TYPE { foo: 'bar' }
mockFetch({ type: 'body', ...DATA })
const request = new FetchRequest()
const result = await triggerMethod<DATA_TYPE>(request, method)
const resultIsEither = isEither<NetworkError, DATA_TYPE>(result)
const resultIsOk = isEither<NetworkError, DATA_TYPE>(result) && result.isOk()
const resultValue = isEither<NetworkError, DATA_TYPE>(result) && result.isOk() ? result.value : null
const resultIsEither = isEither<unknown, DATA_TYPE>(result)
const resultIsOk = isEither<unknown, DATA_TYPE>(result) && result.isOk()
const resultValue = isEither<unknown, DATA_TYPE>(result) && result.isOk() ? result.value : null
expect(resultIsEither).toBe(true)
expect(resultIsOk).toBe(true)
@ -216,9 +216,9 @@ forCheckableMethods('# Should return Either<NetworkError, DATA_TYPE> if checkabl
const request = new FetchRequest()
const result = await triggerMethod(request, method)
const resultIsEither = isEither<NetworkError, void>(result)
const resultIsNotOk = isEither<NetworkError, void>(result) && result.isFail()
const resultValue = isEither<NetworkError, void>(result) && result.isFail() ? result.value : null
const resultIsEither = isEither<NetworkError, unknown>(result)
const resultIsNotOk = isEither<NetworkError, unknown>(result) && result.isFail()
const resultValue = isEither<NetworkError, unknown>(result) && result.isFail() ? result.value : null
expect(resultIsEither).toBe(true)
expect(resultIsNotOk).toBe(true)
@ -233,7 +233,7 @@ describe('# Authorization header', function () {
const request = new FetchRequest()
request.setAuthorizationHeader(TOKEN)
triggerMethod(request, method)
await triggerMethod(request, method)
expect(global.fetch).toBeCalledWith(PATH, expect.objectContaining(OPTIONS))
})

View File

@ -6,39 +6,39 @@ import { Either, fail, success } from './either'
import params2query from './params-to-query'
export interface FetchRequestOptions {
prefix: string;
headers: Record<string, string>;
params: Record<string, string | number | boolean>;
prefix: string
headers: Record<string, string>
params: Record<string, string | number | boolean>
}
export default class FetchRequest {
private defaultOptions: FetchRequestOptions = {
private readonly defaultOptions: FetchRequestOptions = {
prefix: '',
headers: {},
params: {},
}
private options: FetchRequestOptions
private readonly options: FetchRequestOptions
constructor (options: Partial<FetchRequestOptions> = {}) {
this.options = merge(this.defaultOptions, options)
}
private generateFinalUrl = (url: string, options: Partial<FetchRequestOptions> = {}) => {
private readonly generateFinalUrl = (url: string, options: Partial<FetchRequestOptions> = {}) => {
const prefix = options.prefix ?? this.options.prefix
const params = merge(this.options.params, options.params ?? {})
let finalUrl = `${prefix}${url}`
if (Object.keys(params).length) finalUrl += `?${params2query(params)}`
if (Object.keys(params).length > 0) finalUrl += `?${params2query(params)}`
return finalUrl
}
private generateFinalHeaders = (options: Partial<FetchRequestOptions> = {}) => {
private readonly generateFinalHeaders = (options: Partial<FetchRequestOptions> = {}) => {
return merge(this.options.headers, options.headers ?? {})
}
private handleResponse = <T>(response: Response): Promise<Either<NetworkError, T>> => {
private readonly handleResponse = <T>(response: Response): Promise<Either<NetworkError, T>> => {
if (response.ok) {
return response.json().then(json => success(json as T))
}
@ -46,7 +46,7 @@ export default class FetchRequest {
return Promise.resolve(fail(new NetworkError(response)))
}
private handleCorrectResponse = <T>(response: Response): Promise<T> => {
private readonly handleCorrectResponse = <T>(response: Response): Promise<T> => {
if (response.ok) {
return response.json()
}
@ -55,9 +55,9 @@ export default class FetchRequest {
}
private runFetch ({ method, url, data, options }: {
method: 'GET' | 'DELETE' | 'POST' | 'PUT' | 'PATCH',
url: string,
data?: unknown,
method: 'GET' | 'DELETE' | 'POST' | 'PUT' | 'PATCH'
url: string
data?: unknown
options?: Partial<FetchRequestOptions>
}) {
const finalUrl = this.generateFinalUrl(url, options)
@ -65,7 +65,7 @@ export default class FetchRequest {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const fetchOptions: any = { method, headers }
if (data) fetchOptions.body = JSON.stringify(data)
if (data !== undefined) fetchOptions.body = JSON.stringify(data)
return fetch(finalUrl, fetchOptions)
}
@ -118,8 +118,7 @@ export default class FetchRequest {
}
public setAuthorizationHeader (token: string): void {
if (!this.options.headers) this.options.headers = {}
if (token) this.options.headers.Authorization = `Token ${token}`
if (token !== '') this.options.headers.Authorization = `Token ${token}`
}
public deleteAuthorizationHeader (): void {

View File

@ -1,6 +1,6 @@
function get<T> (key: string): T | null {
try {
const value = localStorage.getItem(key) || ''
const value = localStorage.getItem(key) ?? ''
return JSON.parse(value)
} catch (e) {
return null

View File

@ -3,9 +3,9 @@ interface FetchResponseBody {
}
interface FetchResponseFull {
type: 'full'
ok: boolean,
status: number,
statusText:string
ok: boolean
status: number
statusText: string
json: () => Promise<unknown>
}

View File

@ -1,8 +1,8 @@
interface WrapTestsProps <Item> {
task: string
list: Item[]
fn: (item: Item) => void,
only?: boolean,
fn: (item: Item) => void
only?: boolean
testName?: (item: Item, index: number) => string
}
@ -11,7 +11,7 @@ function wrapTests<Item> ({ task, list, fn, testName, only = false }: WrapTestsP
descFn(task, () => {
list.forEach((item, index) => {
const name = testName ? testName(item, index) : ''
const name = testName !== undefined ? testName(item, index) : ''
it(name, () => fn(item))
})
})

148
yarn.lock
View File

@ -1151,13 +1151,13 @@
dependencies:
"@types/yargs-parser" "*"
"@typescript-eslint/eslint-plugin@^4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.6.1.tgz#99d77eb7a016fd5a5e749d2c44a7e4c317eb7da3"
integrity sha512-SNZyflefTMK2JyrPfFFzzoy2asLmZvZJ6+/L5cIqg4HfKGiW2Gr1Go1OyEVqne/U4QwmoasuMwppoBHWBWF2nA==
"@typescript-eslint/eslint-plugin@^4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.7.0.tgz#85c9bbda00c0cb604d3c241f7bc7fb171a2d3479"
integrity sha512-li9aiSVBBd7kU5VlQlT1AqP0uWGDK6JYKUQ9cVDnOg34VNnd9t4jr0Yqc/bKxJr/tDCPDaB4KzoSFN9fgVxe/Q==
dependencies:
"@typescript-eslint/experimental-utils" "4.6.1"
"@typescript-eslint/scope-manager" "4.6.1"
"@typescript-eslint/experimental-utils" "4.7.0"
"@typescript-eslint/scope-manager" "4.7.0"
debug "^4.1.1"
functional-red-black-tree "^1.0.1"
regexpp "^3.0.0"
@ -1175,15 +1175,15 @@
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
"@typescript-eslint/experimental-utils@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.6.1.tgz#a9c691dfd530a9570274fe68907c24c07a06c4aa"
integrity sha512-qyPqCFWlHZXkEBoV56UxHSoXW2qnTr4JrWVXOh3soBP3q0o7p4pUEMfInDwIa0dB/ypdtm7gLOS0hg0a73ijfg==
"@typescript-eslint/experimental-utils@4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.7.0.tgz#8d1058c38bec3d3bbd9c898a1c32318d80faf3c5"
integrity sha512-cymzovXAiD4EF+YoHAB5Oh02MpnXjvyaOb+v+BdpY7lsJXZQN34oIETeUwVT2XfV9rSNpXaIcknDLfupO/tUoA==
dependencies:
"@types/json-schema" "^7.0.3"
"@typescript-eslint/scope-manager" "4.6.1"
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/typescript-estree" "4.6.1"
"@typescript-eslint/scope-manager" "4.7.0"
"@typescript-eslint/types" "4.7.0"
"@typescript-eslint/typescript-estree" "4.7.0"
eslint-scope "^5.0.0"
eslint-utils "^2.0.0"
@ -1198,33 +1198,33 @@
"@typescript-eslint/typescript-estree" "3.10.1"
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/parser@^4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.6.1.tgz#b801bff67b536ecc4a840ac9289ba2be57e02428"
integrity sha512-lScKRPt1wM9UwyKkGKyQDqf0bh6jm8DQ5iN37urRIXDm16GEv+HGEmum2Fc423xlk5NUOkOpfTnKZc/tqKZkDQ==
"@typescript-eslint/parser@^4.0.0", "@typescript-eslint/parser@^4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.7.0.tgz#44bdab0f788b478178368baa65d3365fdc63da1c"
integrity sha512-+meGV8bMP1sJHBI2AFq1GeTwofcGiur8LoIr6v+rEmD9knyCqDlrQcFHR0KDDfldHIFDU/enZ53fla6ReF4wRw==
dependencies:
"@typescript-eslint/scope-manager" "4.6.1"
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/typescript-estree" "4.6.1"
"@typescript-eslint/scope-manager" "4.7.0"
"@typescript-eslint/types" "4.7.0"
"@typescript-eslint/typescript-estree" "4.7.0"
debug "^4.1.1"
"@typescript-eslint/scope-manager@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.6.1.tgz#21872b91cbf7adfc7083f17b8041149148baf992"
integrity sha512-f95+80r6VdINYscJY1KDUEDcxZ3prAWHulL4qRDfNVD0I5QAVSGqFkwHERDoLYJJWmEAkUMdQVvx7/c2Hp+Bjg==
"@typescript-eslint/scope-manager@4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.7.0.tgz#2115526085fb72723ccdc1eeae75dec7126220ed"
integrity sha512-ILITvqwDJYbcDCROj6+Ob0oCKNg3SH46iWcNcTIT9B5aiVssoTYkhKjxOMNzR1F7WSJkik4zmuqve5MdnA0DyA==
dependencies:
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/visitor-keys" "4.6.1"
"@typescript-eslint/types" "4.7.0"
"@typescript-eslint/visitor-keys" "4.7.0"
"@typescript-eslint/types@3.10.1":
version "3.10.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.10.1.tgz#1d7463fa7c32d8a23ab508a803ca2fe26e758727"
integrity sha512-+3+FCUJIahE9q0lDi1WleYzjCwJs5hIsbugIgnbB+dSCYUxl8L6PwmsyOPFZde2hc1DlTo/xnkOgiTLSyAbHiQ==
"@typescript-eslint/types@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.6.1.tgz#d3ad7478f53f22e7339dc006ab61aac131231552"
integrity sha512-k2ZCHhJ96YZyPIsykickez+OMHkz06xppVLfJ+DY90i532/Cx2Z+HiRMH8YZQo7a4zVd/TwNBuRCdXlGK4yo8w==
"@typescript-eslint/types@4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.7.0.tgz#5e95ef5c740f43d942542b35811f87b62fccca69"
integrity sha512-uLszFe0wExJc+I7q0Z/+BnP7wao/kzX0hB5vJn4LIgrfrMLgnB2UXoReV19lkJQS1a1mHWGGODSxnBx6JQC3Sg==
"@typescript-eslint/typescript-estree@3.10.1":
version "3.10.1"
@ -1240,13 +1240,13 @@
semver "^7.3.2"
tsutils "^3.17.1"
"@typescript-eslint/typescript-estree@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.6.1.tgz#6025cce724329413f57e4959b2d676fceeca246f"
integrity sha512-/J/kxiyjQQKqEr5kuKLNQ1Finpfb8gf/NpbwqFFYEBjxOsZ621r9AqwS9UDRA1Rrr/eneX/YsbPAIhU2rFLjXQ==
"@typescript-eslint/typescript-estree@4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.7.0.tgz#539531167f05ba20eb0b6785567076679e29d393"
integrity sha512-5XZRQznD1MfUmxu1t8/j2Af4OxbA7EFU2rbo0No7meb46eHgGkSieFdfV6omiC/DGIBhH9H9gXn7okBbVOm8jw==
dependencies:
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/visitor-keys" "4.6.1"
"@typescript-eslint/types" "4.7.0"
"@typescript-eslint/visitor-keys" "4.7.0"
debug "^4.1.1"
globby "^11.0.1"
is-glob "^4.0.1"
@ -1261,12 +1261,12 @@
dependencies:
eslint-visitor-keys "^1.1.0"
"@typescript-eslint/visitor-keys@4.6.1":
version "4.6.1"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.6.1.tgz#6b125883402d8939df7b54528d879e88f7ba3614"
integrity sha512-owABze4toX7QXwOLT3/D5a8NecZEjEWU1srqxENTfqsY3bwVnl3YYbOh6s1rp2wQKO9RTHFGjKes08FgE7SVMw==
"@typescript-eslint/visitor-keys@4.7.0":
version "4.7.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.7.0.tgz#6783824f22acfc49e754970ed21b88ac03b80e6f"
integrity sha512-aDJDWuCRsf1lXOtignlfiPODkzSxxop7D0rZ91L6ZuMlcMCSh0YyK+gAfo5zN/ih6WxMwhoXgJWC3cWQdaKC+A==
dependencies:
"@typescript-eslint/types" "4.6.1"
"@typescript-eslint/types" "4.7.0"
eslint-visitor-keys "^2.0.0"
"@vue/compiler-core@3.0.2":
@ -3079,6 +3079,19 @@ escodegen@^1.14.1, escodegen@^1.9.1:
optionalDependencies:
source-map "~0.6.1"
eslint-config-standard-with-typescript@^19.0.1:
version "19.0.1"
resolved "https://registry.yarnpkg.com/eslint-config-standard-with-typescript/-/eslint-config-standard-with-typescript-19.0.1.tgz#d486e08a82f6bf43a8e0ef1bc76088e26fe7a587"
integrity sha512-hAKj81+f4a+9lnvpHwZ4XSL672CbwSe5UJ7fTdL/RsQdqs4IjHudMETZuNQwwU7NlYpBTF9se7FRf5Pp7CVdag==
dependencies:
"@typescript-eslint/parser" "^4.0.0"
eslint-config-standard "^14.1.1"
eslint-config-standard@^14.1.1:
version "14.1.1"
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-14.1.1.tgz#830a8e44e7aef7de67464979ad06b406026c56ea"
integrity sha512-Z9B+VR+JIXRxz21udPTL9HpFMyoMUEeX1G251EQ6e05WD9aPVtVBn09XUmZ259wCMlCDmYDSZG62Hhm+ZTJcUg==
eslint-config-standard@^16.0.1:
version "16.0.1"
resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-16.0.1.tgz#9a385eea27f96b7918cb53f07e01e9d10cc56401"
@ -3151,10 +3164,10 @@ eslint-plugin-promise@^4.2.1:
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a"
integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw==
eslint-plugin-standard@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.2.tgz#021211a9f077e63a6847e7bb9ab4247327ac8e0c"
integrity sha512-nKptN8l7jksXkwFk++PhJB3cCDTcXOEyhISIN86Ue2feJ1LFyY3PrY3/xT2keXlJSY5bpmbiTG0f885/YKAvTA==
eslint-plugin-standard@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.1.0.tgz#0c3bf3a67e853f8bbbc580fb4945fbf16f41b7c5"
integrity sha512-ZL7+QRixjTR6/528YNGyDotyffm5OQst/sGxKDwGb9Uqs4In5Egi4+jbobhqJoyoCM6/7v/1A5fhQ7ScMtDjaQ==
eslint-plugin-vue@^7.1.0:
version "7.1.0"
@ -3241,7 +3254,7 @@ eslint@^6.8.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
eslint@^7.11.0:
eslint@^7.11.0, eslint@^7.13.0:
version "7.13.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.13.0.tgz#7f180126c0dcdef327bfb54b211d7802decc08da"
integrity sha512-uCORMuOO8tUzJmsdRtrvcGq5qposf7Rw0LwkTJkoDbOycVQtQjmnhZSuLQnozLE4TmAzlMVV45eCHmQ1OpDKUQ==
@ -3284,49 +3297,6 @@ eslint@^7.11.0:
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
eslint@^7.12.1:
version "7.12.1"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.12.1.tgz#bd9a81fa67a6cfd51656cdb88812ce49ccec5801"
integrity sha512-HlMTEdr/LicJfN08LB3nM1rRYliDXOmfoO4vj39xN6BLpFzF00hbwBoqHk8UcJ2M/3nlARZWy/mslvGEuZFvsg==
dependencies:
"@babel/code-frame" "^7.0.0"
"@eslint/eslintrc" "^0.2.1"
ajv "^6.10.0"
chalk "^4.0.0"
cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
enquirer "^2.3.5"
eslint-scope "^5.1.1"
eslint-utils "^2.1.0"
eslint-visitor-keys "^2.0.0"
espree "^7.3.0"
esquery "^1.2.0"
esutils "^2.0.2"
file-entry-cache "^5.0.1"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
globals "^12.1.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
levn "^0.4.1"
lodash "^4.17.19"
minimatch "^3.0.4"
natural-compare "^1.4.0"
optionator "^0.9.1"
progress "^2.0.0"
regexpp "^3.1.0"
semver "^7.2.1"
strip-ansi "^6.0.0"
strip-json-comments "^3.1.0"
table "^5.2.3"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
espree@^6.1.2, espree@^6.2.1:
version "6.2.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"