1
0

merge upstream

This commit is contained in:
Hazelnoot
2025-03-25 16:14:53 -04:00
1065 changed files with 32953 additions and 20092 deletions
+4 -4
View File
@@ -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";
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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 () => {
+3 -3
View File
@@ -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'));
+1 -3
View File
@@ -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 () => {
+1 -1
View File
@@ -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" */
+5 -5
View File
@@ -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,
},
};
});
+142
View File
@@ -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('これはテストです', 'サンプル'));
});
});
+1 -1
View File
@@ -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';
+6 -6
View File
@@ -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;
+5 -2
View File
@@ -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',
);
});