@things-factory/figure-ui 10.1.147 → 10.1.150
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/bootstrap.ts +10 -2
- package/client/graphql/index.ts +20 -0
- package/client/modeller/canvas.ts +6 -2
- package/client/modeller/carrier-declaration.ts +63 -0
- package/client/modeller/editor.ts +62 -27
- package/client/modeller/figure-carrier.ts +117 -0
- package/client/modeller/figure-cavity-drawing.ts +3 -9
- package/client/modeller/figure-first-save.ts +4 -7
- package/client/modeller/figure-history-panel.ts +2 -3
- package/client/modeller/figure-links.ts +46 -60
- package/client/modeller/figure-material-panel.ts +4 -14
- package/client/modeller/figure-mesh-choice.ts +68 -0
- package/client/modeller/figure-parts.ts +23 -1
- package/client/modeller/figure-preview.ts +2 -2
- package/client/modeller/figure-properties.ts +5 -3
- package/client/modeller/figure-section-editor.ts +12 -33
- package/client/modeller/figure-section-panel.ts +6 -7
- package/client/modeller/figure-slot-layout-panel.ts +208 -0
- package/client/modeller/figure-verdict.ts +21 -31
- package/client/modeller/first-save.ts +23 -0
- package/client/modeller/links.ts +52 -1
- package/client/modeller/material-edit.ts +38 -0
- package/client/modeller/maturity.ts +28 -0
- package/client/modeller/mesh-import.ts +77 -0
- package/client/modeller/modeller-route.ts +9 -0
- package/client/modeller/mounting-part.ts +15 -0
- package/client/modeller/newest-answer.ts +21 -0
- package/client/modeller/preview-model.ts +5 -0
- package/client/modeller/refusals.ts +168 -82
- package/client/modeller/section-controls.ts +25 -1
- package/client/modeller/section-drawing.ts +43 -1
- package/client/modeller/slot-layout-host.ts +140 -0
- package/client/pages/figure-modeller-page.ts +6 -5
- package/client/viewparts/detail-route.ts +7 -0
- package/client/viewparts/figure-detail-dock.ts +1 -3
- package/dist-client/bootstrap.d.ts +1 -1
- package/dist-client/bootstrap.js +9 -2
- package/dist-client/bootstrap.js.map +1 -1
- package/dist-client/graphql/index.d.ts +5 -0
- package/dist-client/graphql/index.js +19 -0
- package/dist-client/graphql/index.js.map +1 -1
- package/dist-client/modeller/canvas.d.ts +2 -0
- package/dist-client/modeller/canvas.js +10 -2
- package/dist-client/modeller/canvas.js.map +1 -1
- package/dist-client/modeller/carrier-declaration.d.ts +31 -0
- package/dist-client/modeller/carrier-declaration.js +53 -0
- package/dist-client/modeller/carrier-declaration.js.map +1 -0
- package/dist-client/modeller/editor.d.ts +13 -0
- package/dist-client/modeller/editor.js +62 -27
- package/dist-client/modeller/editor.js.map +1 -1
- package/dist-client/modeller/figure-carrier.d.ts +26 -0
- package/dist-client/modeller/figure-carrier.js +123 -0
- package/dist-client/modeller/figure-carrier.js.map +1 -0
- package/dist-client/modeller/figure-cavity-drawing.js +3 -11
- package/dist-client/modeller/figure-cavity-drawing.js.map +1 -1
- package/dist-client/modeller/figure-first-save.d.ts +4 -0
- package/dist-client/modeller/figure-first-save.js +5 -8
- package/dist-client/modeller/figure-first-save.js.map +1 -1
- package/dist-client/modeller/figure-history-panel.js +2 -4
- package/dist-client/modeller/figure-history-panel.js.map +1 -1
- package/dist-client/modeller/figure-links.d.ts +4 -1
- package/dist-client/modeller/figure-links.js +47 -57
- package/dist-client/modeller/figure-links.js.map +1 -1
- package/dist-client/modeller/figure-material-panel.d.ts +0 -1
- package/dist-client/modeller/figure-material-panel.js +4 -14
- package/dist-client/modeller/figure-material-panel.js.map +1 -1
- package/dist-client/modeller/figure-mesh-choice.d.ts +16 -0
- package/dist-client/modeller/figure-mesh-choice.js +75 -0
- package/dist-client/modeller/figure-mesh-choice.js.map +1 -0
- package/dist-client/modeller/figure-parts.d.ts +1 -1
- package/dist-client/modeller/figure-parts.js +22 -0
- package/dist-client/modeller/figure-parts.js.map +1 -1
- package/dist-client/modeller/figure-preview.js +2 -2
- package/dist-client/modeller/figure-preview.js.map +1 -1
- package/dist-client/modeller/figure-properties.d.ts +2 -1
- package/dist-client/modeller/figure-properties.js +5 -3
- package/dist-client/modeller/figure-properties.js.map +1 -1
- package/dist-client/modeller/figure-section-editor.d.ts +2 -2
- package/dist-client/modeller/figure-section-editor.js +12 -33
- package/dist-client/modeller/figure-section-editor.js.map +1 -1
- package/dist-client/modeller/figure-section-panel.js +6 -7
- package/dist-client/modeller/figure-section-panel.js.map +1 -1
- package/dist-client/modeller/figure-slot-layout-panel.d.ts +36 -0
- package/dist-client/modeller/figure-slot-layout-panel.js +198 -0
- package/dist-client/modeller/figure-slot-layout-panel.js.map +1 -0
- package/dist-client/modeller/figure-verdict.d.ts +1 -1
- package/dist-client/modeller/figure-verdict.js +19 -37
- package/dist-client/modeller/figure-verdict.js.map +1 -1
- package/dist-client/modeller/first-save.d.ts +10 -0
- package/dist-client/modeller/first-save.js +16 -0
- package/dist-client/modeller/first-save.js.map +1 -1
- package/dist-client/modeller/links.d.ts +26 -1
- package/dist-client/modeller/links.js +43 -0
- package/dist-client/modeller/links.js.map +1 -1
- package/dist-client/modeller/material-edit.d.ts +11 -0
- package/dist-client/modeller/material-edit.js +28 -0
- package/dist-client/modeller/material-edit.js.map +1 -0
- package/dist-client/modeller/maturity.d.ts +15 -0
- package/dist-client/modeller/maturity.js +23 -0
- package/dist-client/modeller/maturity.js.map +1 -1
- package/dist-client/modeller/mesh-import.d.ts +47 -0
- package/dist-client/modeller/mesh-import.js +47 -0
- package/dist-client/modeller/mesh-import.js.map +1 -0
- package/dist-client/modeller/modeller-route.d.ts +5 -0
- package/dist-client/modeller/modeller-route.js +9 -0
- package/dist-client/modeller/modeller-route.js.map +1 -1
- package/dist-client/modeller/mounting-part.d.ts +14 -0
- package/dist-client/modeller/mounting-part.js +10 -0
- package/dist-client/modeller/mounting-part.js.map +1 -0
- package/dist-client/modeller/newest-answer.d.ts +12 -0
- package/dist-client/modeller/newest-answer.js +21 -0
- package/dist-client/modeller/newest-answer.js.map +1 -0
- package/dist-client/modeller/preview-model.d.ts +2 -0
- package/dist-client/modeller/preview-model.js +4 -0
- package/dist-client/modeller/preview-model.js.map +1 -1
- package/dist-client/modeller/refusals.d.ts +26 -5
- package/dist-client/modeller/refusals.js +184 -86
- package/dist-client/modeller/refusals.js.map +1 -1
- package/dist-client/modeller/section-controls.d.ts +17 -1
- package/dist-client/modeller/section-controls.js +18 -0
- package/dist-client/modeller/section-controls.js.map +1 -1
- package/dist-client/modeller/section-drawing.d.ts +24 -1
- package/dist-client/modeller/section-drawing.js +42 -0
- package/dist-client/modeller/section-drawing.js.map +1 -1
- package/dist-client/modeller/slot-layout-host.d.ts +81 -0
- package/dist-client/modeller/slot-layout-host.js +105 -0
- package/dist-client/modeller/slot-layout-host.js.map +1 -0
- package/dist-client/pages/figure-modeller-page.js +5 -4
- package/dist-client/pages/figure-modeller-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/viewparts/detail-route.d.ts +5 -0
- package/dist-client/viewparts/detail-route.js +8 -0
- package/dist-client/viewparts/detail-route.js.map +1 -0
- package/dist-client/viewparts/figure-detail-dock.d.ts +0 -1
- package/dist-client/viewparts/figure-detail-dock.js +1 -3
- package/dist-client/viewparts/figure-detail-dock.js.map +1 -1
- package/package.json +9 -8
- package/test/align.test.ts +0 -9
- package/test/browser/assistant-stand-in.js +32 -0
- package/test/browser/build.check.mjs +77 -0
- package/test/browser/build.mjs +31 -6
- package/test/browser/editing-page.js +224 -0
- package/test/browser/editing.check.mjs +550 -0
- package/test/browser/links-page.js +113 -0
- package/test/browser/links.check.mjs +568 -0
- package/test/browser/modeller.check.mjs +21 -0
- package/test/browser/parts-page.js +120 -0
- package/test/browser/parts.check.mjs +328 -0
- package/test/browser/places-mesh-page.js +36 -0
- package/test/browser/places-mesh.check.mjs +239 -0
- package/test/browser/product-page.check.mjs +682 -0
- package/test/browser/product-page.js +276 -0
- package/test/browser/screen-page.js +112 -0
- package/test/browser/screen-product-page.js +62 -0
- package/test/browser/screen.check.mjs +1003 -0
- package/test/browser/section-page.js +256 -0
- package/test/browser/section.check.mjs +719 -0
- package/test/browser/serve.mjs +20 -12
- package/test/carrier-declaration.test.ts +69 -0
- package/test/cavity-drawing.test.ts +2 -18
- package/test/clip-ai-proposal.test.ts +1 -5
- package/test/clip-consent.test.ts +0 -5
- package/test/clips.test.ts +0 -7
- package/test/command-preview.test.ts +0 -68
- package/test/controls.test.ts +0 -9
- package/test/detail-dock.test.ts +6 -25
- package/test/face-mapping.test.ts +1 -20
- package/test/fasten-drawing.test.ts +0 -23
- package/test/fields.test.ts +6 -33
- package/test/figure-assistant-surface.test.ts +32 -38
- package/test/first-minute.test.ts +3 -55
- package/test/first-save-suggest.test.ts +11 -8
- package/test/first-save.test.ts +4 -26
- package/test/gizmo.test.ts +0 -25
- package/test/joint-fan.test.ts +0 -10
- package/test/keys.test.ts +0 -7
- package/test/layout.test.ts +4 -73
- package/test/links.test.ts +48 -67
- package/test/live.test.ts +0 -34
- package/test/material.test.ts +17 -26
- package/test/maturity.test.ts +13 -16
- package/test/mesh-import.test.ts +76 -0
- package/test/modeller-route.test.ts +3 -19
- package/test/package-download.test.ts +6 -7
- package/test/parts-wiring.test.ts +9 -51
- package/test/preview.test.ts +5 -46
- package/test/properties.test.ts +11 -26
- package/test/proposal-record.test.ts +2 -19
- package/test/recipes.test.ts +0 -15
- package/test/refusals.test.ts +257 -151
- package/test/release-entry.test.ts +1 -9
- package/test/release-panel.test.ts +1 -22
- package/test/resize-with-placement.test.ts +0 -32
- package/test/revert-choice.test.ts +1 -22
- package/test/revert-keeping.test.ts +1 -12
- package/test/save-landed.test.ts +16 -14
- package/test/scene-canvas.test.ts +2 -13
- package/test/section-editor.test.ts +30 -83
- package/test/section-panel.test.ts +22 -17
- package/test/slot-layout-host.test.ts +117 -0
- package/test/theme.test.ts +5 -9
- package/test/verdict.test.ts +44 -41
- package/test/view.test.ts +5 -12
- package/translations/en.json +61 -1
- package/translations/es.json +61 -1
- package/translations/ja.json +61 -1
- package/translations/ko.json +61 -1
- package/translations/ms.json +61 -1
- package/translations/zh.json +61 -1
- package/test/thumbnail.test.ts +0 -29
|
@@ -12,34 +12,14 @@ import { fileURLToPath } from 'node:url'
|
|
|
12
12
|
|
|
13
13
|
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
14
14
|
const editor = read('../client/modeller/editor.ts')
|
|
15
|
-
const panel = read('../client/modeller/figure-parts.ts')
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const listener = editor.slice(editor.indexOf('<figure-parts'), editor.indexOf('</figure-parts>'))
|
|
22
|
-
for (const name of asked) assert.ok(listener.includes(`@${name}=`), `${name} 을 받는 자리가 없다`)
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
test('복제 · 순서 · 삭제는 figure-model 의 부품 편집으로, 세션을 지난다', () => {
|
|
26
|
-
assert.match(editor, /this\.session!\.edit\(\{ kind: 'duplicate-part', target: id \}\)/)
|
|
27
|
-
assert.match(editor, /this\.session!\.edit\(\{ kind: 'move-part', target: id, to \}\)/)
|
|
28
|
-
assert.match(editor, /this\.session!\.edit\(\{ kind: 'remove-part', target: id, \.\.\.\(refitRoom \? \{ refitRoom: true \} : \{\}\) \}\)/)
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
test('작업대에서 가린 부품은 캔버스에서 빠지고, 다른 도형을 열면 풀린다', () => {
|
|
32
|
-
assert.ok(editor.includes('.parts=${this.drawnParts(view.geometry, live)}'))
|
|
33
|
-
const drawn = editor.slice(editor.indexOf(' private drawnParts('), editor.indexOf(' private hold('))
|
|
34
|
-
assert.ok(drawn.includes('parts.filter(body => !this.hiddenParts.has('), '끄는 값을 그릴 때도 가린 부품은 빠진다')
|
|
35
|
-
const reset = editor.slice(editor.indexOf('protected willUpdate'), editor.indexOf('private run('))
|
|
36
|
-
assert.match(reset, /this\.hiddenParts = new Set\(\)/)
|
|
37
|
-
})
|
|
16
|
+
/*
|
|
17
|
+
* Each event the panel sends answered by the editor -- picked, moved, duplicated, removed, added, hidden -- as one step
|
|
18
|
+
* of the session, and the workbench's hiding let go when another figure opens: test/browser/parts.check.mjs.
|
|
19
|
+
*/
|
|
38
20
|
|
|
39
21
|
test('지울 수 없는 부품은 사람의 말로 거절하고, 지우며 풀어 준 것은 사람의 말로 알린다 — 다섯 말 모두', () => {
|
|
40
|
-
/*
|
|
41
|
-
assert.match(editor, /private removePart[\s\S]*?partRefusalOf\(error, id,/)
|
|
42
|
-
assert.match(editor, /private removePart[\s\S]*?this\.notice = removalNoticeOf\(view\.removal,/, '지운 뒤 풀어 준 것을 알린다')
|
|
22
|
+
/* The reason is told apart in refusals.test.ts; that the editor tells it, and what a removal let go of, is parts.check.mjs's. */
|
|
43
23
|
for (const lang of ['ko', 'en', 'ja', 'zh', 'ms', 'es']) {
|
|
44
24
|
const table = JSON.parse(read(`../translations/${lang}.json`))
|
|
45
25
|
for (const key of ['part-is-referenced', 'part-in-declared-space', 'part-row-along', 'part-row-carries'])
|
|
@@ -50,19 +30,8 @@ test('지울 수 없는 부품은 사람의 말로 거절하고, 지우며 풀
|
|
|
50
30
|
}
|
|
51
31
|
})
|
|
52
32
|
|
|
53
|
-
test('좁은 칸에서도 고른 줄의 이름과 조작이 다 보인다 — 조작은 이름 아래 줄로', () => {
|
|
54
|
-
assert.match(panel, /container-type: inline-size/)
|
|
55
|
-
const narrow = panel.slice(panel.indexOf('@container (max-width: 199px)'))
|
|
56
|
-
assert.match(narrow, /li\[selected\] \{\s*flex-wrap: wrap;/)
|
|
57
|
-
assert.match(narrow, /li\[selected\] div\[ops\] \{\s*flex-basis: 100%;/)
|
|
58
|
-
})
|
|
59
|
-
|
|
60
33
|
test('팔레트는 시작 모양만 낸다 — 둥근 상자와 통은 상자의 모서리·속 공간으로 만든다 (ADR-0100 §2.1·§3.3)', () => {
|
|
61
|
-
|
|
62
|
-
const kinds = [...recipes.matchAll(/kind: '([\w-]+)'/g)].map(m => m[1])
|
|
63
|
-
assert.deepEqual(kinds, ['box', 'cylinder', 'sphere', 'frustum', 'polygon', 'pyramid', 'plate', 'wall', 'portal'])
|
|
64
|
-
/* A part made so is still called by what it is: its icon in the parts list, its name over the properties (links.ts). */
|
|
65
|
-
assert.match(panel, /'rounded-box': 'crop_square'/)
|
|
34
|
+
/* The nine starting shapes, and a rounded box listed with its own icon, are the browser check's (test/browser/parts.check.mjs). */
|
|
66
35
|
for (const lang of ['ko', 'en', 'ja', 'zh', 'ms', 'es'])
|
|
67
36
|
assert.ok(JSON.parse(read(`../translations/${lang}.json`))['figure.label.primitive-rounded-box'], lang)
|
|
68
37
|
})
|
|
@@ -70,22 +39,11 @@ test('팔레트는 시작 모양만 낸다 — 둥근 상자와 통은 상자의
|
|
|
70
39
|
test('부품 이름은 figure-model 의 rename-part 로 바꾸고, 거절은 까닭별로 사람의 말로 한다', () => {
|
|
71
40
|
assert.match(editor, /this\.session!\.edit\(\{ kind: 'rename-part', target: from, name \}\)/)
|
|
72
41
|
assert.match(editor, /this\.selected = name/, '바꾼 이름의 부품이 그대로 골라져 있다')
|
|
73
|
-
|
|
42
|
+
/* The reason is the kernel's refusal (ADR-0127): the screen does not check the name again (refusals.test.ts makes all three). */
|
|
43
|
+
assert.match(editor, /this\.error = partNameRefusalOf\(error, /)
|
|
74
44
|
for (const lang of ['ko', 'en', 'ja', 'zh', 'ms', 'es']) {
|
|
75
45
|
const table = JSON.parse(read(`../translations/${lang}.json`))
|
|
76
46
|
for (const key of ['figure.text.part-name-taken', 'figure.text.part-name-invalid']) assert.ok(table[key]?.includes('{name}'), `${lang}: ${key}`)
|
|
47
|
+
assert.ok(table['figure.text.part-name-has-nested']?.includes('{nested}'), `${lang}: part-name-has-nested`)
|
|
77
48
|
}
|
|
78
49
|
})
|
|
79
|
-
|
|
80
|
-
test('거절은 앱의 알림(notify)이나 확인 창(OxPrompt)으로 — 모델러가 따로 그리는 띠는 없다 (2026-09-27)', () => {
|
|
81
|
-
assert.doesNotMatch(editor, /role="alert" class="error"/, '따로 그리던 빨간 띠가 없다')
|
|
82
|
-
assert.doesNotMatch(editor, /class="notice"/, '따로 그리던 알림 줄이 없다')
|
|
83
|
-
const tell = editor.slice(editor.indexOf(' private tell('), editor.indexOf(' protected willUpdate('))
|
|
84
|
-
assert.match(tell, /else notify\(\{ level: 'error', message: this\.error \}\)/, '길이 없는 거절은 error 알림 — 닫을 때까지 남는다')
|
|
85
|
-
assert.match(tell, /if \(retry\) this\.ask\(this\.error, retry\)/, '이어 할 길이 있으면 묻는다')
|
|
86
|
-
const ask = editor.slice(editor.indexOf(' private async ask('), editor.indexOf(' protected willUpdate('))
|
|
87
|
-
assert.match(ask, /OxPrompt\.open\(\{[\s\S]*confirmButton: \{ text: retry\.label \}/, '앱의 확인 창에서, 그 길의 이름으로')
|
|
88
|
-
assert.match(ask, /if \(!agreed\) return[\s\S]*retry\.run\(\)/, '확인하면 바로 진행한다')
|
|
89
|
-
assert.match(tell, /notify\(\{ level: 'info', message: this\.notice \}\)/, '지우며 풀어 준 것은 info 로')
|
|
90
|
-
assert.match(editor, /updated\(changed: PropertyValues<this>\) \{\s*super\.updated\?\.\(changed\)\s*this\.tell\(changed\)/)
|
|
91
|
-
})
|
package/test/preview.test.ts
CHANGED
|
@@ -4,14 +4,10 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { test } from 'node:test'
|
|
6
6
|
import assert from 'node:assert/strict'
|
|
7
|
-
import { readFileSync } from 'node:fs'
|
|
8
|
-
import { fileURLToPath } from 'node:url'
|
|
9
7
|
|
|
10
8
|
import { addFigureBox, createFigureAsset } from '@hatiolab/figure-model'
|
|
11
9
|
|
|
12
|
-
import { authoredSizeOf, PREVIEW_WAYS, previewClampsOf, previewInstances, setupPartOf } from '../client/modeller/preview-model.ts'
|
|
13
|
-
|
|
14
|
-
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
10
|
+
import { authoredSizeOf, PREVIEW_WAYS, previewClampsOf, previewInstances, previewTypeOf, setupPartOf } from '../client/modeller/preview-model.ts'
|
|
15
11
|
|
|
16
12
|
test('여덟 — 기준과 일곱 조합, 한 줄에 넷, 늘린 축만 두 배 · 높이는 늘 적는다', () => {
|
|
17
13
|
assert.deepEqual(PREVIEW_WAYS.map(w => w.name), ['base', 'x', 'y', 'z', 'x·y', 'x·z', 'y·z', 'x·y·z'])
|
|
@@ -30,15 +26,10 @@ test('크기를 선언하지 않은 도형은 부품이 차지하는 범위를
|
|
|
30
26
|
assert.deepEqual(authoredSizeOf(asset), { x: 300, y: 200, z: 100 })
|
|
31
27
|
})
|
|
32
28
|
|
|
33
|
-
test('
|
|
34
|
-
|
|
35
|
-
assert.
|
|
36
|
-
assert.
|
|
37
|
-
const preview = read('../client/modeller/figure-preview.ts')
|
|
38
|
-
assert.ok(preview.includes('registerFigure(type, asset)') && preview.includes('unregisterFigure(this.registered)'))
|
|
39
|
-
assert.ok(preview.includes('`figure-preview-${this.context || \'new\'}`'))
|
|
40
|
-
assert.ok(preview.includes("kind: 'set-state-defaults'"), '이 자세를 기본으로')
|
|
41
|
-
assert.ok(preview.includes('dialShape('), '각도는 다이얼로')
|
|
29
|
+
test('미리보기는 제 타입으로 등록한다 — 남의 도면을 건드리지 않는다', () => {
|
|
30
|
+
/* Going to the preview and back, and the registration standing and going with it, are the browser check's (test/browser/screen.check.mjs). */
|
|
31
|
+
assert.equal(previewTypeOf(''), 'figure-preview-new', '저장 전 도형')
|
|
32
|
+
assert.equal(previewTypeOf('abc'), 'figure-preview-abc')
|
|
42
33
|
})
|
|
43
34
|
|
|
44
35
|
test('미리보기 — 선언하지 않은 크기를 묻는 변형은 그려지는 크기를 말한다(높이만 따르는 조명탑, 아키텍트 판정 09-25)', async () => {
|
|
@@ -51,15 +42,6 @@ test('미리보기 — 선언하지 않은 크기를 묻는 변형은 그려지
|
|
|
51
42
|
assert.deepEqual(clamps['x'], [{ axis: 'x', asked: 400, used: 200 }])
|
|
52
43
|
assert.deepEqual(clamps['y'], [{ axis: 'y', asked: 4000, used: 3000 }], '높이도 선언 최대까지')
|
|
53
44
|
assert.deepEqual(clamps['x·y·z'].map(c => c.axis), ['x', 'y', 'z'])
|
|
54
|
-
const view = readFileSync(fileURLToPath(new URL('../client/modeller/figure-preview.ts', import.meta.url)), 'utf8')
|
|
55
|
-
assert.ok(view.includes("i18next.t('figure.text.preview-clamped'"), '범례에 적는다')
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
test('미리보기로 가도 고른 부품이 남는다 — 화면에서 빠진 캔버스는 선택을 알리지 않는다(U03, 2026-10-03)', () => {
|
|
59
|
-
const canvas = read('../client/modeller/canvas.ts')
|
|
60
|
-
const handler = canvas.slice(canvas.indexOf("root.on('selected'"), canvas.indexOf("root.on('selected'") + 900)
|
|
61
|
-
assert.ok(handler.includes('if (!this.isConnected) return'), '장면을 치울 때 비워진 선택을 편집기에 알리지 않는다')
|
|
62
|
-
assert.ok(handler.indexOf('if (!this.isConnected) return') < handler.indexOf("new CustomEvent('part-selected'"), '알리기 전에 거른다')
|
|
63
45
|
})
|
|
64
46
|
|
|
65
47
|
test('미리보기 크기 안내는 편집에서 고른 부품부터 — 안내에서 고른 것이 먼저, 없는 부품은 건너뛴다', () => {
|
|
@@ -68,27 +50,4 @@ test('미리보기 크기 안내는 편집에서 고른 부품부터 — 안내
|
|
|
68
50
|
assert.equal(setupPartOf('', 'leg', ['frame', 'roller']), 'frame', '크기 규칙이 없는 부품이면 첫 부품')
|
|
69
51
|
assert.equal(setupPartOf('gone', '', ['frame']), 'frame', '사라진 부품은 건너뛴다')
|
|
70
52
|
assert.equal(setupPartOf('', '', []), '')
|
|
71
|
-
const editor = read('../client/modeller/editor.ts')
|
|
72
|
-
const tag = editor.slice(editor.indexOf('<figure-preview'), editor.indexOf('</figure-preview>'))
|
|
73
|
-
assert.ok(tag.includes('.selected=${this.selected}'), '편집기가 고른 부품을 넘긴다')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
test('미리보기 아래의 크기 안내와 조작값은 한 줄에서 줄을 바꾼다 — 좁은 폭에서 겹치지 않는다(1024 폭, 2026-10-03)', () => {
|
|
77
|
-
const preview = read('../client/modeller/figure-preview.ts')
|
|
78
|
-
const style = (sel: string) => preview.slice(preview.indexOf(sel + ' {'), preview.indexOf('}', preview.indexOf(sel + ' {')))
|
|
79
|
-
assert.match(style('div[foot]'), /position: absolute/)
|
|
80
|
-
assert.match(style('div[foot]'), /flex-wrap: wrap-reverse/)
|
|
81
|
-
assert.doesNotMatch(style('div[setup]'), /position: absolute/, '안내가 제 모서리에 따로 서지 않는다')
|
|
82
|
-
assert.doesNotMatch(style('div[clips]'), /position: absolute/, '조작값이 제 모서리에 따로 서지 않는다')
|
|
83
|
-
const foot = preview.slice(preview.indexOf('<div foot>'))
|
|
84
|
-
assert.ok(foot.indexOf('<div setup>') < foot.indexOf('this.renderDrivers('), '둘 다 한 줄 안에')
|
|
85
|
-
})
|
|
86
|
-
|
|
87
|
-
test('미리보기 재생 속도는 실제로 도는 값을 보인다 — 움직이기 전에는 0(멈춤), 1.00 으로 보이며 서 있지 않는다(2026-10-03)', () => {
|
|
88
|
-
const preview = read('../client/modeller/figure-preview.ts')
|
|
89
|
-
const drivers = preview.slice(preview.indexOf('clips.map(clip =>'))
|
|
90
|
-
assert.ok(drivers.includes('this.driving[clip] ?? 0'), '아무것도 보내지 않은 clip 은 0 으로 그린다')
|
|
91
|
-
assert.ok(!drivers.slice(0, 600).includes('this.driving[clip] ?? 1'))
|
|
92
|
-
const drive = preview.slice(preview.indexOf('private drive('), preview.indexOf('private give('))
|
|
93
|
-
assert.ok(drive.includes("this.tellInstances('clips'"), '속도는 drive 에서만 보낸다 — 그래서 보이는 값도 보낸 값뿐이다')
|
|
94
53
|
})
|
package/test/properties.test.ts
CHANGED
|
@@ -13,6 +13,7 @@ import { addFigureBox, applyFigureAuthoring, createFigureAsset, inspectFigureAss
|
|
|
13
13
|
|
|
14
14
|
import { tagsOf, figureFigureFacts } from '../client/modeller/figure-facts.ts'
|
|
15
15
|
import { occupancyFromParts } from '../client/modeller/occupancy.ts'
|
|
16
|
+
import { offeredMountingOf } from '../client/modeller/mounting-part.ts'
|
|
16
17
|
import { revisionOf } from './revision-of.ts'
|
|
17
18
|
|
|
18
19
|
const read = (path: string) => readFileSync(fileURLToPath(new URL(path, import.meta.url)), 'utf8')
|
|
@@ -59,33 +60,14 @@ test('태그 줄은 쉼표로 나뉘어 목록이 된다', () => {
|
|
|
59
60
|
assert.deepEqual(tagsOf(''), [], '빈 줄은 전부 지우는 것이다')
|
|
60
61
|
})
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
assert.ok(/<figure-properties\s+slot="figure"/.test(page), '도형 속성은 부품을 고르지 않았을 때 속성 탭에 선다')
|
|
68
|
-
assert.ok(editor.includes('<slot name="figure"></slot>'))
|
|
69
|
-
assert.ok(/@command=\$\{this\.onCommand\}/.test(page) && /@catalog=\$\{this\.onCatalog\}/.test(page))
|
|
70
|
-
const run = page.slice(page.indexOf('private runCommand'), page.indexOf('private onCatalog'))
|
|
71
|
-
assert.ok(/this\.session\.command\(actionOf\(\)\)/.test(run), '명령은 세션을 지난다 — 되돌리기가 먹는다')
|
|
72
|
-
const catalog = page.slice(page.indexOf('private onCatalog'), page.indexOf('private released'))
|
|
73
|
-
assert.ok(/updateFigure\(id, patch\)/.test(catalog), '분류 · 태그는 행에 쓴다')
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
test('이름을 바꾸면 제목 줄도 바뀐다 — 셸은 알려 줄 때만 제목을 다시 읽는다', () => {
|
|
77
|
-
const changed = page.slice(page.indexOf('private changed = () =>'), page.indexOf('private async readRow'))
|
|
78
|
-
assert.ok(/view\.name !== this\.titled[\s\S]*this\.updateContext\(\)/.test(changed))
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
test('발행한 뒤에도 행의 타입이 남는다 — 새로 짜면 잠긴 타입 칸이 빈다', () => {
|
|
82
|
-
const released = page.slice(page.indexOf('private released'), page.indexOf('private reverted'))
|
|
83
|
-
assert.ok(/this\.row = \{ \.\.\.this\.row, state:/.test(released))
|
|
84
|
-
})
|
|
63
|
+
/*
|
|
64
|
+
The page around the tab -- the tab hung in the editor, a command one step of the session's history, category and tags
|
|
65
|
+
written to the row, the title following a rename, the type kept after a release -- is checked in
|
|
66
|
+
test/browser/product-page.check.mjs.
|
|
67
|
+
*/
|
|
85
68
|
|
|
86
69
|
test('속성 탭의 말은 다섯 말 모두에 있다', () => {
|
|
87
70
|
const tab = read('../client/modeller/figure-properties.ts')
|
|
88
|
-
assert.ok(tab.includes('occupancyFromParts(this.revision.asset, placement)'), '고른 배치 기준으로 선언한다')
|
|
89
71
|
const keys = [...tab.matchAll(/'(figure\.[a-z.-]*[a-z])'/g)].map(m => m[1])
|
|
90
72
|
for (const face of ['left', 'right', 'bottom', 'top', 'back', 'front']) keys.push(`figure.label.face-${face}`)
|
|
91
73
|
for (const one of ['floor', 'ceiling', 'center']) keys.push(`figure.label.placement-${one}`)
|
|
@@ -104,6 +86,9 @@ test('장착면은 도형이 평면에 닿는 부품으로 권한다 — 다리
|
|
|
104
86
|
const facts = figureFigureFacts(revisionOf(asset))
|
|
105
87
|
assert.deepEqual(facts.suggested, { part: 'leg', face: 'bottom' })
|
|
106
88
|
assert.equal(facts.parts[0], 'bed', '목록의 첫 부품은 바닥이다')
|
|
107
|
-
|
|
108
|
-
assert.
|
|
89
|
+
assert.deepEqual(offeredMountingOf(facts), { part: 'leg', face: 'bottom' }, 'where it meets its plane')
|
|
90
|
+
assert.deepEqual(offeredMountingOf(facts, { part: 'bed', face: 'top' }), { part: 'bed', face: 'top' }, 'a part picked comes first')
|
|
91
|
+
assert.deepEqual(offeredMountingOf({ ...facts, mounting: { part: 'bed', face: 'bottom' } }), { part: 'bed', face: 'bottom' }, 'then the one set, before the suggestion')
|
|
92
|
+
assert.deepEqual(offeredMountingOf(facts, { part: 'gone' }), { part: 'leg', face: 'bottom' }, 'a part no longer there is passed over')
|
|
93
|
+
assert.deepEqual(offeredMountingOf({ parts: ['bed'] }), { part: 'bed', face: 'bottom' }, 'nothing to suggest: the first part')
|
|
109
94
|
})
|
|
@@ -94,25 +94,10 @@ test('the key travels from the card to the modeller, on a revision and on a new
|
|
|
94
94
|
say
|
|
95
95
|
)
|
|
96
96
|
assert.deepEqual(opened, [K2])
|
|
97
|
-
|
|
98
|
-
const take = page.slice(page.indexOf(' private takeNewFigureProposal'), page.indexOf(' private askFirstSave'))
|
|
99
|
-
assert.ok(take.includes('if (waiting.key) this.session.createUnder(waiting.key)'))
|
|
100
|
-
assert.ok(take.includes('this.session.applyProposal(waiting.steps, view.revision!, view.context!, waiting.key)'))
|
|
101
|
-
assert.ok(read('../client/figure-assistant.ts').includes('const opened = pendNewFigure(steps, key)'))
|
|
97
|
+
/* The page taking a new figure's steps under the key, and saving it under that key, is checked in product-page.check.mjs. */
|
|
102
98
|
})
|
|
103
99
|
|
|
104
|
-
|
|
105
|
-
const page = read('../client/pages/figure-modeller-page.ts')
|
|
106
|
-
const provide = page.slice(page.indexOf(' private provideAssistant = '), page.indexOf(' private withdrawAssistant('))
|
|
107
|
-
assert.ok(provide.includes('...this.assistantFocus()'), 'read at the moment of sending')
|
|
108
|
-
assert.ok(provide.includes('selection: { part: focus.part, context, revision }'))
|
|
109
|
-
assert.ok(provide.includes('trying: { ...focus.trying, context, revision }'))
|
|
110
|
-
/* Not in the key, the label or the anchor: selecting is not a new subject. */
|
|
111
|
-
assert.ok(provide.includes('key: `figure:${id}`'))
|
|
112
|
-
const editor = read('../client/modeller/editor.ts')
|
|
113
|
-
const choose = editor.slice(editor.indexOf(' private choose('), editor.indexOf(' private choose(') + 400)
|
|
114
|
-
assert.ok(!choose.includes('notifyAssistantSurface') && !editor.includes('notifyAssistantSurface'), 'selecting does not tell the dock')
|
|
115
|
-
})
|
|
100
|
+
/* What the dock hears of the selected part and the preview, and that selecting tells it nothing, is checked in product-page.check.mjs. */
|
|
116
101
|
|
|
117
102
|
test('the dock checks the result from the server: saved is accepted and named, nothing recorded is not known', async () => {
|
|
118
103
|
const { proposalOutcomeFrom } = await import('../client/modeller/ai-proposal.js')
|
|
@@ -120,7 +105,5 @@ test('the dock checks the result from the server: saved is accepted and named, n
|
|
|
120
105
|
const sayKo = (key: string, params: Record<string, string> = {}) => words[key].replace(/\{(\w+)\}/g, (_: string, k: string) => params[k] ?? '')
|
|
121
106
|
assert.deepEqual(proposalOutcomeFrom([{ figureId: 'x', type: 'LIDDED', name: '뚜껑 상자' }], sayKo), { verdict: 'accepted', note: '저장된 도형에 들어 있습니다: 뚜껑 상자' })
|
|
122
107
|
assert.equal(proposalOutcomeFrom([], sayKo), undefined, 'not saved is not known, never refused')
|
|
123
|
-
const page = read('../client/pages/figure-modeller-page.ts')
|
|
124
|
-
assert.ok(page.includes('proposalOutcomeFrom(await fetchProposalOutcome(proposalKey)'), 'the surface asks the server')
|
|
125
108
|
for (const lang of ['en', 'ja', 'ko', 'ms', 'zh', 'es']) assert.ok(JSON.parse(read(`../translations/${lang}.json`))['figure.text.proposal-saved-into'], lang)
|
|
126
109
|
})
|
package/test/recipes.test.ts
CHANGED
|
@@ -62,23 +62,8 @@ test('작동 방식은 레시피에서 셈한다 — 미닫이 문: 두 문짝
|
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
test('모델러 — 부품 칸의 단추가 카탈로그를 열고, 넣으면 한 단계로 들어가고 창이 닫힌다; 목록은 페이지가 서버에서 한 번 읽는다', () => {
|
|
65
|
-
const parts = read('../client/modeller/figure-parts.ts')
|
|
66
|
-
assert.ok(parts.includes("this.ask('open-recipe-catalog', {})"))
|
|
67
|
-
const editor = read('../client/modeller/editor.ts')
|
|
68
|
-
const insert = editor.slice(editor.indexOf(' private insertRecipe('), editor.indexOf(' /** The design values of the asset being edited. */'))
|
|
69
|
-
assert.ok(insert.includes('figureRecipeIdFor(asset, checked)') && insert.includes('this.session!.applyRecipe(steps)') && insert.includes('this.catalogOpen = false'))
|
|
70
|
-
assert.ok(insert.includes('this.recipeError = recipeRefusalOf(error, (key, params) => i18next.t(key, params)) ?? this.said(error)'), '거절은 사람의 말로, 막힌 단계와 함께 — 커널의 영어가 아니라 (2026-09-27)')
|
|
71
65
|
const page = read('../client/pages/figure-modeller-page.ts')
|
|
72
66
|
assert.ok(page.includes("availableRecipes(i18next.language || 'en')") && page.includes('.templates=${this.templates}'))
|
|
73
|
-
const catalog = read('../client/modeller/figure-recipe-catalog.ts')
|
|
74
|
-
assert.ok(catalog.includes('describeFigureRecipe(t.recipe)'), '부품 수는 셈한다')
|
|
75
|
-
assert.ok(catalog.includes("${this.guide ? html`<ox-markdown"), '설명이 없으면 아무것도 두지 않는다 — 「준비 중」 없음')
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
test('넣기는 카탈로그에서 온다 — 편집기는 카탈로그 요소에서 insert-recipe 를 듣는다 (잘못 옮겨진 연결, 09-26)', () => {
|
|
79
|
-
const editor = read('../client/modeller/editor.ts')
|
|
80
|
-
const catalog = editor.slice(editor.indexOf('<figure-recipe-catalog'), editor.indexOf('</figure-recipe-catalog>'))
|
|
81
|
-
assert.ok(catalog.includes('@insert-recipe=${(e: CustomEvent) => this.insertRecipe(e.detail.recipe, e.detail.values)}'))
|
|
82
67
|
})
|
|
83
68
|
|
|
84
69
|
test('검색은 제목이 찾는 말인 것부터 — 「다리」에 다리 넷이 사다리보다 먼저 (walk 1, 2026-09-26)', () => {
|