merge upstream
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { aiScriptReadline, createAiScriptEnv } from '@/scripts/aiscript/api.js';
|
||||
import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js';
|
||||
import { errors, Interpreter, Parser, values } from '@syuilo/aiscript';
|
||||
import {
|
||||
afterAll,
|
||||
@@ -33,11 +33,11 @@ async function exe(script: string): Promise<values.Value[]> {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
let $iMock = vi.hoisted<Partial<typeof import('@/account.js').$i> | null >(
|
||||
let $iMock = vi.hoisted<Partial<typeof import('@/i.js').$i> | null >(
|
||||
() => null
|
||||
);
|
||||
|
||||
vi.mock('@/account.js', () => {
|
||||
vi.mock('@/i.js', () => {
|
||||
return {
|
||||
get $i() {
|
||||
return $iMock;
|
||||
@@ -59,7 +59,7 @@ vi.mock('@/os.js', () => {
|
||||
|
||||
const misskeyApiMock = vi.hoisted(() => vi.fn());
|
||||
|
||||
vi.mock('@/scripts/misskey-api.js', () => {
|
||||
vi.mock('@/utility/misskey-api.js', () => {
|
||||
return { misskeyApi: misskeyApiMock };
|
||||
});
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { assertStringAndIsIn } from "@/scripts/aiscript/common.js";
|
||||
import { assertStringAndIsIn } from "@/aiscript/common.js";
|
||||
import { values } from "@syuilo/aiscript";
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { registerAsUiLib } from '@/aiscript/ui.js';
|
||||
import { errors, Interpreter, Parser, values } from '@syuilo/aiscript';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
import { type Ref, ref } from 'vue';
|
||||
@@ -18,8 +19,7 @@ import type {
|
||||
AsUiText,
|
||||
AsUiTextarea,
|
||||
AsUiTextInput,
|
||||
} from '@/scripts/aiscript/ui.js';
|
||||
import { registerAsUiLib } from '@/scripts/aiscript/ui.js';
|
||||
} from '@/aiscript/ui.js';
|
||||
|
||||
type ExeResult = {
|
||||
root: AsUiRoot;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
import { assert, describe, test } from 'vitest';
|
||||
import { searchEmoji } from '@/scripts/search-emoji.js';
|
||||
import { searchEmoji } from '@/utility/search-emoji.js';
|
||||
|
||||
describe('emoji autocomplete', () => {
|
||||
test('名前の完全一致は名前の前方一致より優先される', async () => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { describe, test, assert, afterEach } from 'vitest';
|
||||
import { render, cleanup, type RenderResult } from '@testing-library/vue';
|
||||
import { defaultStoreState } from './init.js';
|
||||
import { preferState } from './init.js';
|
||||
import { getEmojiName } from '@@/js/emojilist.js';
|
||||
import { components } from '@/components/index.js';
|
||||
import { directives } from '@/directives/index.js';
|
||||
@@ -21,12 +21,12 @@ describe('Emoji', () => {
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
defaultStoreState.emojiStyle = '';
|
||||
preferState.emojiStyle = '';
|
||||
});
|
||||
|
||||
describe('MkEmoji', () => {
|
||||
test('Should render selector-less heart with color in native mode', async () => {
|
||||
defaultStoreState.emojiStyle = 'native';
|
||||
preferState.emojiStyle = 'native';
|
||||
const mkEmoji = await renderEmoji('\u2764'); // monochrome heart
|
||||
assert.ok(mkEmoji.queryByText('\u2764\uFE0F')); // colored heart
|
||||
assert.ok(!mkEmoji.queryByText('\u2764'));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { afterEach, assert, describe, test } from 'vitest';
|
||||
import { cleanup, render, type RenderResult } from '@testing-library/vue';
|
||||
import './init';
|
||||
import type * as Misskey from 'misskey-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { directives } from '@/directives/index.js';
|
||||
import { components } from '@/components/index.js';
|
||||
import XHome from '@/pages/user/home.vue';
|
||||
@@ -42,8 +42,6 @@ describe('XHome', () => {
|
||||
const anchor = home.container.querySelector<HTMLAnchorElement>('a[href^="https://example.com/"]');
|
||||
assert.exists(anchor, 'anchor to the remote exists');
|
||||
assert.strictEqual(anchor?.href, 'https://example.com/@user/profile');
|
||||
|
||||
assert.ok(anchor?.parentElement?.classList.contains('warn'), 'the parent is a warning');
|
||||
});
|
||||
|
||||
test('The remote caution should fall back to uri if url is null', async () => {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { I18n } from '../../frontend-shared/js/i18n.js'; // @@で参照できなかったので
|
||||
import { ParameterizedString } from '../../../locales/index.js';
|
||||
import type { ParameterizedString } from '../../../locales/index.js';
|
||||
|
||||
/* eslint "sharkey/locale":"off" */
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ updateI18n(locales['en-US']);
|
||||
// XXX: misskey-js panics if WebSocket is not defined
|
||||
vi.stubGlobal('WebSocket', class WebSocket extends EventTarget { static CLOSING = 2; });
|
||||
|
||||
export const defaultStoreState: Record<string, unknown> = {
|
||||
export const preferState: Record<string, unknown> = {
|
||||
|
||||
// なんかtestがうまいこと動かないのでここに書く
|
||||
dataSaver: {
|
||||
@@ -29,11 +29,11 @@ export const defaultStoreState: Record<string, unknown> = {
|
||||
|
||||
};
|
||||
|
||||
// XXX: defaultStore somehow becomes undefined in vitest?
|
||||
vi.mock('@/store.js', () => {
|
||||
// XXX: store somehow becomes undefined in vitest?
|
||||
vi.mock('@/preferences.js', () => {
|
||||
return {
|
||||
defaultStore: {
|
||||
state: defaultStoreState,
|
||||
prefer: {
|
||||
s: preferState,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { assert, beforeEach, describe, test } from 'vitest';
|
||||
import {
|
||||
normalizeString,
|
||||
initIntlString,
|
||||
normalizeStringWithHiragana,
|
||||
compareStringEquals,
|
||||
compareStringIncludes,
|
||||
} from '@/utility/intl-string.js';
|
||||
|
||||
// 共通のテストを実行するヘルパー関数
|
||||
const runCommonTests = (normalizeFn: (str: string) => string) => {
|
||||
test('全角英数字が半角の小文字になる', () => {
|
||||
// ローマ字にならないようにする
|
||||
const input = 'B123';
|
||||
const expected = 'b123';
|
||||
assert.strictEqual(normalizeFn(input), expected);
|
||||
});
|
||||
test('濁点・半濁点が正しく結合される', () => {
|
||||
const input = 'か\u3099';
|
||||
const expected = 'が';
|
||||
assert.strictEqual(normalizeFn(input), expected);
|
||||
});
|
||||
test('小文字に揃う', () => {
|
||||
// ローマ字にならないようにする
|
||||
const input = 'tSt';
|
||||
const expected = 'tst';
|
||||
assert.strictEqual(normalizeFn(input), expected);
|
||||
});
|
||||
test('文字列の前後の空白が削除される', () => {
|
||||
const input = ' tst ';
|
||||
const expected = 'tst';
|
||||
assert.strictEqual(normalizeFn(input), expected);
|
||||
});
|
||||
};
|
||||
|
||||
describe('normalize string', () => {
|
||||
runCommonTests(normalizeString);
|
||||
|
||||
test('異体字の正規化 (ligature)', () => {
|
||||
const input = 'fi';
|
||||
const expected = 'fi';
|
||||
assert.strictEqual(normalizeString(input), expected);
|
||||
});
|
||||
|
||||
test('半角カタカナは全角に変換される', () => {
|
||||
const input = 'カタカナ';
|
||||
const expected = 'カタカナ';
|
||||
assert.strictEqual(normalizeString(input), expected);
|
||||
});
|
||||
});
|
||||
|
||||
// normalizeStringWithHiraganaのテスト
|
||||
describe('normalize string with hiragana', () => {
|
||||
beforeEach(async () => {
|
||||
await initIntlString(true);
|
||||
});
|
||||
|
||||
// 共通テスト
|
||||
describe('共通のnormalizeStringテスト', () => {
|
||||
runCommonTests(normalizeStringWithHiragana);
|
||||
});
|
||||
|
||||
test('半角カタカナがひらがなに変換される', () => {
|
||||
const input = 'カタカナ';
|
||||
const expected = 'かたかな';
|
||||
assert.strictEqual(normalizeStringWithHiragana(input), expected);
|
||||
});
|
||||
|
||||
// normalizeStringWithHiragana特有のテスト
|
||||
test('カタカナがひらがなに変換される・伸ばし棒はハイフンに変換される', () => {
|
||||
const input = 'カタカナひーらがーな';
|
||||
const expected = 'かたかなひ-らが-な';
|
||||
assert.strictEqual(normalizeStringWithHiragana(input), expected);
|
||||
});
|
||||
|
||||
test('ローマ字がひらがなに変換される', () => {
|
||||
const input = 'ro-majimohiragananinarimasu';
|
||||
const expected = 'ろ-まじもひらがなになります';
|
||||
assert.strictEqual(normalizeStringWithHiragana(input), expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('compareStringEquals', () => {
|
||||
beforeEach(async () => {
|
||||
await initIntlString(true);
|
||||
});
|
||||
|
||||
test('完全一致ならtrue', () => {
|
||||
assert.isTrue(compareStringEquals('テスト', 'テスト'));
|
||||
});
|
||||
|
||||
test('大文字・小文字の違いを無視', () => {
|
||||
assert.isTrue(compareStringEquals('TeSt', 'test'));
|
||||
});
|
||||
|
||||
test('全角・半角の違いを無視', () => {
|
||||
assert.isTrue(compareStringEquals('ABC', 'abc'));
|
||||
});
|
||||
|
||||
test('カタカナとひらがなの違いを無視', () => {
|
||||
assert.isTrue(compareStringEquals('カタカナ', 'かたかな'));
|
||||
});
|
||||
|
||||
test('ローマ字をひらがなと比較可能', () => {
|
||||
assert.isTrue(compareStringEquals('hiragana', 'ひらがな'));
|
||||
});
|
||||
|
||||
test('異なる文字列はfalse', () => {
|
||||
assert.isFalse(compareStringEquals('テスト', 'サンプル'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('compareStringIncludes', () => {
|
||||
test('部分一致ならtrue', () => {
|
||||
assert.isTrue(compareStringIncludes('これはテストです', 'テスト'));
|
||||
});
|
||||
|
||||
test('大文字・小文字の違いを無視', () => {
|
||||
assert.isTrue(compareStringIncludes('This is a Test', 'test'));
|
||||
});
|
||||
|
||||
test('全角・半角の違いを無視', () => {
|
||||
assert.isTrue(compareStringIncludes('ABCDE', 'abc'));
|
||||
});
|
||||
|
||||
test('カタカナとひらがなの違いを無視', () => {
|
||||
assert.isTrue(compareStringIncludes('カタカナのテスト', 'かたかな'));
|
||||
});
|
||||
|
||||
test('ローマ字をひらがなと比較可能', () => {
|
||||
assert.isTrue(compareStringIncludes('これはhiraganaのテスト', 'ひらがな'));
|
||||
});
|
||||
|
||||
test('異なる文字列はfalse', () => {
|
||||
assert.isFalse(compareStringIncludes('これはテストです', 'サンプル'));
|
||||
});
|
||||
});
|
||||
@@ -6,7 +6,7 @@
|
||||
import { describe, test, assert, afterEach } from 'vitest';
|
||||
import { render, cleanup, type RenderResult } from '@testing-library/vue';
|
||||
import './init';
|
||||
import type * as Misskey from 'misskey-js';
|
||||
import * as Misskey from 'misskey-js';
|
||||
import { components } from '@/components/index.js';
|
||||
import { directives } from '@/directives/index.js';
|
||||
import MkMediaImage from '@/components/MkMediaImage.vue';
|
||||
|
||||
@@ -12,10 +12,10 @@ describe('Scroll', () => {
|
||||
/* 動作しない(happy-domのバグ?)
|
||||
test('Initial onScrollTop callback for connected elements', () => {
|
||||
const { document } = new Window();
|
||||
const div = document.createElement('div');
|
||||
const div = window.document.createElement('div');
|
||||
assert.strictEqual(div.scrollTop, 0);
|
||||
|
||||
document.body.append(div);
|
||||
window.document.body.append(div);
|
||||
|
||||
let called = false;
|
||||
onScrollTop(div as any as HTMLElement, () => called = true);
|
||||
@@ -26,7 +26,7 @@ describe('Scroll', () => {
|
||||
|
||||
test('No onScrollTop callback for disconnected elements', () => {
|
||||
const { document } = new Window();
|
||||
const div = document.createElement('div');
|
||||
const div = window.document.createElement('div');
|
||||
assert.strictEqual(div.scrollTop, 0);
|
||||
|
||||
let called = false;
|
||||
@@ -40,10 +40,10 @@ describe('Scroll', () => {
|
||||
/* 動作しない(happy-domのバグ?)
|
||||
test('Initial onScrollBottom callback for connected elements', () => {
|
||||
const { document } = new Window();
|
||||
const div = document.createElement('div');
|
||||
const div = window.document.createElement('div');
|
||||
assert.strictEqual(div.scrollTop, 0);
|
||||
|
||||
document.body.append(div);
|
||||
window.document.body.append(div);
|
||||
|
||||
let called = false;
|
||||
onScrollBottom(div as any as HTMLElement, () => called = true);
|
||||
@@ -54,7 +54,7 @@ describe('Scroll', () => {
|
||||
|
||||
test('No onScrollBottom callback for disconnected elements', () => {
|
||||
const { document } = new Window();
|
||||
const div = document.createElement('div');
|
||||
const div = window.document.createElement('div');
|
||||
assert.strictEqual(div.scrollTop, 0);
|
||||
|
||||
let called = false;
|
||||
|
||||
@@ -24,7 +24,10 @@ describe('MkUrlPreview', () => {
|
||||
};
|
||||
}
|
||||
|
||||
fetchMock.mockOnceIf(/^\/url?/, () => {
|
||||
fetchMock.mockOnceIf((req) => {
|
||||
const url = new URL(req.url);
|
||||
return url.pathname === '/url';
|
||||
}, () => {
|
||||
return {
|
||||
status: 200,
|
||||
body: JSON.stringify(summary),
|
||||
@@ -98,7 +101,7 @@ describe('MkUrlPreview', () => {
|
||||
assert.strictEqual(iframe?.src, 'https://example.local/player?autoplay=1&auto_play=1');
|
||||
assert.strictEqual(
|
||||
iframe?.sandbox.toString(),
|
||||
'allow-popups allow-scripts allow-storage-access-by-user-activation allow-same-origin',
|
||||
'allow-popups allow-popups-to-escape-sandbox allow-scripts allow-storage-access-by-user-activation allow-same-origin',
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user