コミットを比較
3 コミット
| 作成者 | SHA1 | 日付 | |
|---|---|---|---|
| 46e6d94edb | |||
| 817cd6ae73 | |||
| dc7353304f |
@@ -154,6 +154,14 @@ npm run preview
|
|||||||
一つの文字列補間へまとめる、中間変数へ分ける、`format` を使ふ、heredoc を
|
一つの文字列補間へまとめる、中間変数へ分ける、`format` を使ふ、heredoc を
|
||||||
使ふ、array 又は Hash を組み立ててから処理する、条件式全体を括弧で囲む、
|
使ふ、array 又は Hash を組み立ててから処理する、条件式全体を括弧で囲む、
|
||||||
method へ抽出する、のいづれかへ書き換へる。
|
method へ抽出する、のいづれかへ書き換へる。
|
||||||
|
- Ruby では、一つの文字列を、改行をまたいだ隣接文字列 literal として記述しない。
|
||||||
|
- Ruby では、method argument 内でも、複数の文字列 literal を区切りなしで縦に
|
||||||
|
並べない。
|
||||||
|
- RSpec の `describe`、`context`、`it` 等の description が長い場合は、意味を
|
||||||
|
保ったまま一行へ収まる文言へ短縮する。
|
||||||
|
- 文字列を短縮できない場合は、用途に応じて `format`、heredoc 又は中間変数を
|
||||||
|
検討する。
|
||||||
|
- ただし RSpec description では、原則として簡潔な一行の文字列を使ふ。
|
||||||
- formatter 又は自動修正にも、Ruby の行末バックスラッシュを生成させない。
|
- formatter 又は自動修正にも、Ruby の行末バックスラッシュを生成させない。
|
||||||
- 新規 code だけでなく、今回触れる Ruby code にも行末バックスラッシュを残さない。
|
- 新規 code だけでなく、今回触れる Ruby code にも行末バックスラッシュを残さない。
|
||||||
- 例へば class body 内の array は、class body の 2 空白を基準に、更に 4 空白
|
- 例へば class body 内の array は、class body の 2 空白を基準に、更に 4 空白
|
||||||
@@ -251,6 +259,21 @@ result = first_value + \
|
|||||||
|
|
||||||
Bad:
|
Bad:
|
||||||
|
|
||||||
|
```rb
|
||||||
|
it(
|
||||||
|
'returns 409 when stale changes '
|
||||||
|
'do not conflict'
|
||||||
|
) do
|
||||||
|
```
|
||||||
|
|
||||||
|
Good:
|
||||||
|
|
||||||
|
```rb
|
||||||
|
it 'returns mergeable 409 for stale non-conflicting changes' do
|
||||||
|
```
|
||||||
|
|
||||||
|
Bad:
|
||||||
|
|
||||||
```rb
|
```rb
|
||||||
records.each {
|
records.each {
|
||||||
do_work(_1) }
|
do_work(_1) }
|
||||||
@@ -551,8 +574,32 @@ and layout reuse, follow `frontend/AGENTS.md`.
|
|||||||
wording and placement before implementing it.
|
wording and placement before implementing it.
|
||||||
- Do not invent replacement copy when removing unrequested wording.
|
- Do not invent replacement copy when removing unrequested wording.
|
||||||
- Do not create, modify, or run tests unless the user explicitly asks for
|
- Do not create, modify, or run tests unless the user explicitly asks for
|
||||||
test work. When the user asks for tests, keep working and rerun them until
|
test work. When the user asks for tests, keep working within the permitted
|
||||||
they pass or the remaining failure is clearly blocked.
|
test-file scope and rerun them until they pass or the remaining failure is
|
||||||
|
clearly blocked.
|
||||||
|
- Test-only work includes adding, updating, deleting, reorganising, or fixing
|
||||||
|
SyntaxError in tests. During test-only work, do not modify production code.
|
||||||
|
- During test-only work, do not change production constants, behaviour, API
|
||||||
|
contracts, validation, routes, authentication, permissions, UI, copy,
|
||||||
|
dependencies, limits, thresholds, defaults, migrations, schema, or
|
||||||
|
environment settings to satisfy tests.
|
||||||
|
- Do not make production code match failing tests, mock assumptions, fixtures,
|
||||||
|
snapshots, old expectations, or stale setup. This includes changing
|
||||||
|
production constants merely because a test expects a different value.
|
||||||
|
- If test work reveals a production bug, spec mismatch, or missing behaviour,
|
||||||
|
stop without modifying production code and report: the failing test or
|
||||||
|
discovered issue, the related production file, the actual behaviour, the
|
||||||
|
expected behaviour, and why a production change appears necessary.
|
||||||
|
- Modify production code for test failures only when the user explicitly asks
|
||||||
|
for that production change. Do not expand a test task into a production task
|
||||||
|
on your own authority.
|
||||||
|
- If the user explicitly asks for both production implementation and test
|
||||||
|
updates, implement production code to the confirmed specification first,
|
||||||
|
then add or update tests to verify that specification. Never roll production
|
||||||
|
behaviour back to satisfy old tests.
|
||||||
|
- If it is unclear whether the test or the production implementation is stale,
|
||||||
|
or a test cannot be corrected without changing production code, ask the user
|
||||||
|
instead of guessing.
|
||||||
|
|
||||||
## Backend rules
|
## Backend rules
|
||||||
|
|
||||||
|
|||||||
@@ -1712,10 +1712,7 @@ RSpec.describe 'Posts API', type: :request do
|
|||||||
expect(post_record.reload.title).to eq('updated by other user')
|
expect(post_record.reload.title).to eq('updated by other user')
|
||||||
end
|
end
|
||||||
|
|
||||||
it(
|
it 'returns mergeable 409 for stale non-conflicting tag changes without merge' do
|
||||||
'returns 409 with mergeable true when stale tag changes '
|
|
||||||
'do not conflict but merge is not requested'
|
|
||||||
) do
|
|
||||||
sign_in_as(member)
|
sign_in_as(member)
|
||||||
|
|
||||||
base_version = create_post_version_for!(post_record.reload)
|
base_version = create_post_version_for!(post_record.reload)
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
RSpec.describe 'Wiki body search', type: :request do
|
|
||||||
let!(:user) { create_member_user! }
|
|
||||||
|
|
||||||
it 'searches wiki pages by body text' do
|
|
||||||
pending '#336 で対応予定'
|
|
||||||
|
|
||||||
Wiki::Commit.create_content!(
|
|
||||||
tag_name: TagName.create!(name: 'wiki_body_search_hit'),
|
|
||||||
body: 'unique body keyword for wiki search',
|
|
||||||
created_by_user: user,
|
|
||||||
message: 'init')
|
|
||||||
|
|
||||||
Wiki::Commit.create_content!(
|
|
||||||
tag_name: TagName.create!(name: 'wiki_body_search_miss'),
|
|
||||||
body: 'ordinary body',
|
|
||||||
created_by_user: user,
|
|
||||||
message: 'init')
|
|
||||||
|
|
||||||
get '/wiki/search', params: { body: 'unique body keyword' }
|
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
|
||||||
expect(json.map { |page| page['title'] }).to include('wiki_body_search_hit')
|
|
||||||
expect(json.map { |page| page['title'] }).not_to include('wiki_body_search_miss')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
require 'rails_helper'
|
|
||||||
|
|
||||||
RSpec.describe 'Wiki restore', type: :request do
|
|
||||||
let!(:user) { create_member_user! }
|
|
||||||
|
|
||||||
def auth_headers user
|
|
||||||
{ 'X-Transfer-Code' => user.inheritance_code }
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'restores wiki page to previous version' do
|
|
||||||
pending '#337 で対応予定'
|
|
||||||
|
|
||||||
page =
|
|
||||||
Wiki::Commit.create_content!(
|
|
||||||
tag_name: TagName.create!(name: 'wiki_restore_page'),
|
|
||||||
body: 'v1',
|
|
||||||
created_by_user: user,
|
|
||||||
message: 'init')
|
|
||||||
|
|
||||||
v1 = page.wiki_versions.order(:version_no).last
|
|
||||||
|
|
||||||
Wiki::Commit.content!(
|
|
||||||
page:,
|
|
||||||
body: 'v2',
|
|
||||||
created_user: user,
|
|
||||||
message: 'edit',
|
|
||||||
base_revision_id: page.current_revision.id)
|
|
||||||
|
|
||||||
post "/wiki/#{ page.id }/restore",
|
|
||||||
params: { version_no: v1.version_no },
|
|
||||||
headers: auth_headers(user)
|
|
||||||
|
|
||||||
expect(response).to have_http_status(:ok)
|
|
||||||
expect(page.reload.body).to eq('v1')
|
|
||||||
expect(page.wiki_versions.order(:version_no).last.event_type).to eq('restore')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -29,15 +29,15 @@ describe ('post new review URL state', () => {
|
|||||||
.toEqual (['one', 'two'])
|
.toEqual (['one', 'two'])
|
||||||
})
|
})
|
||||||
|
|
||||||
it ('allows at most a 4095-byte request target', () => {
|
it ('allows at most a 6 143 byte request target', () => {
|
||||||
const baseUrl = 'https://example.com/'
|
const baseUrl = 'https://example.com/'
|
||||||
const baseLength = postNewReviewPathByteLength ([baseUrl])
|
const baseLength = postNewReviewPathByteLength ([baseUrl])
|
||||||
const allowed = `${ baseUrl }${ 'a'.repeat (4_095 - baseLength) }`
|
const allowed = `${ baseUrl }${ 'a'.repeat (6_143 - baseLength) }`
|
||||||
const denied = `${ allowed }a`
|
const denied = `${ allowed }a`
|
||||||
|
|
||||||
expect (postNewReviewPathByteLength ([allowed])).toBe (4_095)
|
expect (postNewReviewPathByteLength ([allowed])).toBe (6_143)
|
||||||
expect (isPostNewReviewPathWithinLimit ([allowed])).toBe (true)
|
expect (isPostNewReviewPathWithinLimit ([allowed])).toBe (true)
|
||||||
expect (postNewReviewPathByteLength ([denied])).toBe (4_096)
|
expect (postNewReviewPathByteLength ([denied])).toBe (6_144)
|
||||||
expect (isPostNewReviewPathWithinLimit ([denied])).toBe (false)
|
expect (isPostNewReviewPathWithinLimit ([denied])).toBe (false)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const POST_NEW_REVIEW_PATH_PREFIX = '/posts/new?urls='
|
const POST_NEW_REVIEW_PATH_PREFIX = '/posts/new?urls='
|
||||||
const MAX_POST_NEW_REVIEW_TARGET_BYTES = 4_096
|
const MAX_POST_NEW_REVIEW_TARGET_BYTES = 6_144
|
||||||
|
|
||||||
const textEncoder = new TextEncoder ()
|
const textEncoder = new TextEncoder ()
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ describe ('PostImportSourcePage', () => {
|
|||||||
const input = screen.getByRole ('textbox', { name: '' })
|
const input = screen.getByRole ('textbox', { name: '' })
|
||||||
|
|
||||||
fireEvent.change (input, {
|
fireEvent.change (input, {
|
||||||
target: { value: `https://example.com/${ 'a'.repeat (4_100) }` } })
|
target: { value: `https://example.com/${ 'a'.repeat (6_200) }` } })
|
||||||
|
|
||||||
expect (screen.getByRole ('button', { name: '次へ' })).toBeDisabled ()
|
expect (screen.getByRole ('button', { name: '次へ' })).toBeDisabled ()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
import { describe, it } from 'vitest'
|
|
||||||
|
|
||||||
describe ('pending high-level browser coverage', () => {
|
|
||||||
it.todo ('adds MSW-backed API boundary tests in a follow-up issue')
|
|
||||||
it.todo ('covers TheatreDetailPage with timer polling, comment posting, and next-post updates')
|
|
||||||
it.todo ('covers NicoTagListPage linking and pagination against realistic API payloads')
|
|
||||||
it.todo ('covers TagDetailSidebar drag/drop parent-child editing with pointer-event fidelity')
|
|
||||||
it.todo ('covers TopNav desktop and mobile menu flows as browser-level integration tests')
|
|
||||||
it.todo ('covers full App bootstrap for user creation, user verification, and 503 handling')
|
|
||||||
})
|
|
||||||
新しい課題から参照
ユーザをブロックする