import * as glassEasel from 'glass-easel'
import { type BehaviorConstructor, type ComponentConstructor, MiniProgramEnv, types } from '../src'
import { tmpl } from './base/env'
const domHtml = (elem: glassEasel.Element): string => {
const domElem = elem.getBackendElement() as unknown as Element
return domElem.innerHTML
}
describe('define', () => {
test('define basic behaviors and components', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addStyleSheet('app', 'app.css')
codeSpace.addStyleSheet('path/to/comp', 'path/to/comp.css')
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{a}}-{{b}}
`),
)
const beh = codeSpace
.behavior()
.definition({
data: {
a: 123,
},
})
.register()
codeSpace
.component('path/to/comp')
.definition({
behaviors: [beh],
properties: {
b: Number,
},
})
.register()
const ab = env.associateBackend()
ab.registerStyleSheetContent('app.css', '')
ab.registerStyleSheetContent('path/to/comp.css', '.ab { color: red }')
const root = ab.createRoot('body', codeSpace, 'path/to/comp?b=456')
expect(domHtml(root.getComponent())).toBe('123-456
')
})
test('define basic behaviors and components with global vars', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
const callOrder = [] as number[]
codeSpace.addComponentStaticConfig('path/to/comp', {})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{a}}-{{b}}-{{c}}
`),
)
const g = {} as { Behavior: BehaviorConstructor; Component: ComponentConstructor }
codeSpace.globalComponentEnv(g, 'path/to/comp', () => {
const Behavior = g.Behavior
const Component = g.Component
const beh = Behavior({
data: {
a: 123,
},
observers: {
a() {
callOrder.push(1)
},
},
})
const traitBeh = Behavior.trait<{ a: () => void }>()
Component({
options: {
propertyEarlyInit: true,
},
behaviors: [beh],
properties: {
b: Number,
},
data: () => ({
c: 789,
}),
observers: [
{
fields: 'b',
observer() {
callOrder.push(2)
},
},
],
created() {
callOrder.push(3)
},
attached() {
this.setData({
a: 321,
b: 654,
} as { b: number })
callOrder.push(4)
},
detached() {
callOrder.push(5)
},
moved() {
callOrder.push(6)
},
ready() {
callOrder.push(7)
},
lifetimes: {
invalid() {
/* empty */
},
},
pageLifetimes: {
invalid() {
/* empty */
},
},
relations: {
invalid: {
type: 'parent',
target: traitBeh,
},
},
externalClasses: [],
})
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp?b=456')
expect(domHtml(root.getComponent())).toBe('123-456-789
')
glassEasel.Element.pretendAttached(root.getComponent())
expect(domHtml(root.getComponent())).toBe('321-654-789
')
root.getComponent().triggerLifetime('ready', [])
root.getComponent().triggerLifetime('moved', [])
glassEasel.Element.pretendDetached(root.getComponent())
expect(callOrder).toStrictEqual([2, 3, 1, 2, 4, 7, 6, 5])
})
test('define legacy pages', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
const callOrder = [] as number[]
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{a}}-{{b}}
`),
)
codeSpace.componentEnv('path/to/comp', ({ Behavior, Page }) => {
const beh = Behavior()
.property('a', String)
.lifetime('attached', function () {
expect(this.hasBehavior(beh)).toBe(true)
const self = this as unknown as {
myMethod: () => number
myData: any
}
expect(self.myMethod()).toBe(123)
expect(self.myData).toStrictEqual({ myField: 456 })
callOrder.push(1)
})
.register()
Page({
behaviors: [beh],
data: {
b: 'def',
},
myMethod() {
return 123
},
myData: {
myField: 456,
},
})
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp?a=abc')
glassEasel.Element.pretendAttached(root.getComponent())
expect(domHtml(root.getComponent())).toBe('abc-def
')
expect(callOrder).toStrictEqual([1])
})
test('options generics', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('comp/a', {
component: true,
componentGenerics: {
c: true,
},
})
codeSpace.addCompiledTemplate(
'comp/a',
tmpl(`
`),
)
codeSpace.addStyleSheet('comp/a', undefined, 'A')
codeSpace.componentEnv('comp/a', ({ Component }) => {
Component().register()
})
codeSpace.addComponentStaticConfig('comp/b', {
component: true,
})
codeSpace.addCompiledTemplate(
'comp/b',
tmpl(`
B
`),
)
codeSpace.addStyleSheet('comp/b', undefined, 'B')
codeSpace.componentEnv('comp/b', ({ Component }) => {
Component().register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
a: '/comp/a',
b: '/comp/b',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe(
'B',
)
})
test('options placeholder', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('comp/a', {
component: true,
})
codeSpace.addCompiledTemplate(
'comp/a',
tmpl(`
A
`),
)
codeSpace.addStyleSheet('comp/a', undefined, 'A')
codeSpace.componentEnv('comp/a', ({ Component }) => {
Component().register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
a: '/comp/b',
ph: '/comp/a',
},
componentPlaceholder: {
a: 'ph',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.addStyleSheet('path/to/comp', undefined, 'COMP')
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('A
')
codeSpace.addComponentStaticConfig('comp/b', {
component: true,
})
codeSpace.addCompiledTemplate(
'comp/b',
tmpl(`
B
`),
)
codeSpace.addStyleSheet('comp/b', undefined, 'B')
codeSpace.componentEnv('comp/b', ({ Component }) => {
Component().register()
})
expect(domHtml(root.getComponent())).toBe('B')
})
test('options pureDataPattern (js)', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{_a}}-{{b}}
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component()
.options({
pureDataPattern: /^_/,
})
.data(() => ({
_a: 123,
b: 456,
}))
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('-456
')
})
test('options pureDataPattern (json)', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('path/to/comp', {
pureDataPattern: '^_',
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{_a}}-{{b}}
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component()
.options({
pureDataPattern: /^_/,
})
.data(() => ({
_a: 123,
b: 456,
}))
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('-456
')
})
test('options addGlobalClass', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addStyleSheet('child/comp', 'empty-style-sheet', 'child-comp')
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
addGlobalClass: true,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
addGlobalClass: true,
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
ab.registerStyleSheetContent('empty-style-sheet', '')
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe(
'',
)
})
test('options styleIsolation shared', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addStyleSheet('child/comp', 'empty-style-sheet', 'child-comp')
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
styleIsolation: types.StyleIsolation.Shared,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.register()
})
codeSpace.addStyleSheet('path/to/comp', 'empty-style-sheet', 'comp')
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
styleIsolation: types.StyleIsolation.PageShared,
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
ab.registerStyleSheetContent('empty-style-sheet', '')
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('')
})
test('options styleIsolation apply-shared', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addStyleSheet('child/comp', 'empty-style-sheet', 'child-comp')
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
styleIsolation: types.StyleIsolation.ApplyShared,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.register()
})
codeSpace.addStyleSheet('path/to/comp', 'empty-style-sheet', 'comp')
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
styleIsolation: types.StyleIsolation.PageApplyShared,
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
ab.registerStyleSheetContent('empty-style-sheet', '')
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe(
'',
)
})
test('options styleIsolation isolated', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addStyleSheet('child/comp', 'empty-style-sheet', 'child-comp')
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
styleIsolation: types.StyleIsolation.Isolated,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.register()
})
codeSpace.addStyleSheet('path/to/comp', 'empty-style-sheet', 'comp')
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
styleIsolation: types.StyleIsolation.PageIsolated,
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
ab.registerStyleSheetContent('empty-style-sheet', '')
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe(
'',
)
})
test('options dataDeepCopy', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('path/to/comp', {})
codeSpace.addCompiledTemplate('path/to/comp', tmpl(''))
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component({
options: {
dataDeepCopy: glassEasel.DeepCopyKind.None,
},
data: {
a: [1, 2, 3],
},
})
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
const a = [3, 2, 1]
root.getComponent().setData({
a,
})
expect(root.getComponent().data.a).toBe(a)
})
test('options propertyPassingDeepCopy', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
const callOrder = [] as number[]
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
`),
)
// eslint-disable-next-line arrow-body-style
const childDef = codeSpace.componentEnv('child/comp', ({ Component }) => {
return Component()
.options({
virtualHost: true,
dataDeepCopy: glassEasel.DeepCopyKind.None,
propertyPassingDeepCopy: glassEasel.DeepCopyKind.None,
})
.property('p', Object)
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
styleIsolation: types.StyleIsolation.PageIsolated,
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component()
.options({
dataDeepCopy: glassEasel.DeepCopyKind.None,
propertyPassingDeepCopy: glassEasel.DeepCopyKind.None,
})
.data(() => ({
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
a: Object.create(Object.prototype, {
f: { enumerable: true, value: 123 },
__test: { enumerable: false, value: 456 },
}),
}))
.lifetime('attached', function () {
const child = this.selectComponent('#c', childDef)!
expect(child.data.p).toBe(this.data.a)
callOrder.push(1)
})
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
glassEasel.Element.pretendAttached(root.getComponent())
expect(callOrder).toStrictEqual([1])
})
test('options propertyComparer', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
let execArr: string[] = []
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
{{a}}
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) =>
Component()
.property('a', { type: Number, value: 123 })
.observer('a', () => {
execArr.push('a')
})
.register(),
)
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
})
codeSpace.componentEnv('path/to/comp', ({ Component }) =>
Component()
.options({
propertyComparer: (a: unknown, b: unknown) => a !== b,
})
.property('a', { type: Number, value: 123 })
.register(),
)
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
const rootComp = root.getComponent()
expect(execArr).toEqual(['a'])
execArr = []
rootComp.setData({ a: 233 })
expect(execArr).toEqual(['a'])
execArr = []
rootComp.setData({ a: 233 })
expect(execArr).toEqual([])
})
test('definition filter', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{a}}-{{b}}
`),
)
const beh = codeSpace
.behavior()
.data(() => ({
a: 123,
}))
.register()
const filterBeh = codeSpace
.behavior()
.behavior(beh)
.definition({
definitionFilter: (def: types.GeneralComponentDefinition) => {
// eslint-disable-next-line no-param-reassign
def.data = { b: 456 }
},
})
.register()
codeSpace
.component('path/to/comp')
.definition({
behaviors: [filterBeh],
})
.register()
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('123-456
')
})
test('chaining behaviors', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{a}}-{{b}}
`),
)
const beh = codeSpace
.behavior()
.data(() => ({
a: 123,
}))
.register()
codeSpace
.component('path/to/comp')
.behavior(beh)
.data(() => ({
b: 456,
}))
.register()
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('123-456
')
})
test('chaining filters', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{a}}-{{b}}
`),
)
type TAdd = { data: (this: T) => T }
type TRemove = 'data' | 'property'
const beh = codeSpace
.behavior()
.chainingFilter((chain) => {
const oldData = chain.data.bind(chain)
const newData = function () {
return oldData(() => ({
a: 123,
}))
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Object.create(chain, {
data: { value: newData },
})
})
.register()
codeSpace
.component('path/to/comp')
.data(() => ({
b: 456,
}))
.behavior(beh)
.data()
.register()
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('123-456
')
})
test('chaining external classes', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.externalClasses(['a-class'])
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('')
})
test('chaining methods', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
const callOrder = [] as number[]
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
})
// eslint-disable-next-line arrow-body-style
const childType = codeSpace.componentEnv('child/comp', ({ Component }) => {
return Component()
.methods({
childFn() {
return 123
},
})
.lifetime('attached', function () {
// eslint-disable-next-line no-use-before-define
expect(this.selectOwnerComponent(parentType)!.parentFn()).toBe(456)
callOrder.push(1)
})
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
// eslint-disable-next-line arrow-body-style
const parentType = codeSpace.componentEnv('path/to/comp', ({ Component }) => {
return Component()
.lifetime('attached', function () {
expect(this.selectComponent('#c', childType)!.childFn()).toBe(123)
callOrder.push(2)
})
.init(({ method }) => {
const parentFn = method(() => 456)
return { parentFn }
})
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
glassEasel.Element.pretendAttached(root.getComponent())
expect(callOrder).toStrictEqual([2, 1])
})
test('chaining static data', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('path/to/comp', {})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{ text }}
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component()
.staticData({
text: 'abc',
})
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('abc
')
})
test('chaining observer', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
{{aa}}
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.property('a', Number)
.data(() => ({
aa: 10,
}))
.observer('a', function () {
this.setData({
aa: this.data.a * 10,
})
})
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component()
.data(() => ({
b: 1,
bb: 10,
}))
.observer('b', function () {
this.setData({
bb: this.data.b * 10,
})
})
.lifetime('attached', function () {
this.setData({ b: 2 })
})
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('100')
glassEasel.Element.pretendAttached(root.getComponent())
expect(domHtml(root.getComponent())).toBe('200')
})
test('chaining pageLifetime', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('child/comp', {
component: true,
})
codeSpace.addCompiledTemplate(
'child/comp',
tmpl(`
{{a}}-{{b}}
`),
)
codeSpace.componentEnv('child/comp', ({ Component }) => {
Component()
.options({
virtualHost: true,
})
.property('a', Number)
.data(() => ({
b: 0,
}))
.pageLifetime('show', function () {
this.setData({
b: 456,
})
})
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
child: '/child/comp',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component()
.data(() => ({
a: 0,
}))
.pageLifetime('show', function (a: number) {
this.setData({ a })
})
.register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('0-0')
root.getComponent().triggerPageLifetime('show', [123])
expect(domHtml(root.getComponent())).toBe('123-456')
})
test('chaining relation', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addComponentStaticConfig('child/list', {
component: true,
})
codeSpace.addCompiledTemplate(
'child/list',
tmpl(`
{{count}}
`),
)
codeSpace.addStyleSheet('child/list', undefined, 'LIST')
// eslint-disable-next-line arrow-body-style
const listDef = codeSpace.componentEnv('child/list', ({ Component }) => {
return Component()
.data(() => ({
count: 0,
}))
.relation('item', {
type: 'child',
linked(target) {
// eslint-disable-next-line no-use-before-define
expect(target.asInstanceOf(itemDef)).not.toBe(null)
this.setData({
count: this.getRelationNodes('item').length,
})
},
})
.register()
})
codeSpace.addComponentStaticConfig('child/item', {
component: true,
})
codeSpace.addStyleSheet('child/item', undefined, 'ITEM')
// eslint-disable-next-line arrow-body-style
const itemDef = codeSpace.componentEnv('child/item', ({ Component }) => {
return Component()
.data(() => ({
count: 0,
}))
.init(({ relation }) => {
relation({
type: 'parent',
target: listDef,
})
})
.register()
})
codeSpace.addComponentStaticConfig('path/to/comp', {
usingComponents: {
list: '/child/list',
item: '/child/item',
},
})
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
`),
)
codeSpace.componentEnv('path/to/comp', ({ Component }) => {
Component().register()
})
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
glassEasel.Element.pretendAttached(root.getComponent())
expect(domHtml(root.getComponent())).toBe(
'2
',
)
})
test('chaining extraThisFieldsType', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addCompiledTemplate(
'path/to/comp',
tmpl(`
{{hello}}
`),
)
const beh = codeSpace
.behavior()
.extraThisFieldsType<{ behDelayedData: string }>()
.lifetime('created', function () {
this.behDelayedData = 'Say hello'
})
.register()
const beh2 = codeSpace
.behavior()
.behavior(beh)
.extraThisFieldsType<{ beh2DelayedData: string }>()
.lifetime('created', function () {
this.beh2DelayedData = `${this.behDelayedData} to`
})
.register()
codeSpace
.component('path/to/comp')
.behavior(beh2)
.extraThisFieldsType<{ delayedData: string }>()
.data(() => ({
hello: '',
}))
.lifetime('created', function () {
this.delayedData = `${this.beh2DelayedData} glass-easel!`
this.setData({
hello: this.delayedData,
})
})
.register()
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'path/to/comp')
expect(domHtml(root.getComponent())).toBe('Say hello to glass-easel!
')
})
test('extraThisFieldsType with selectComponent', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
codeSpace.addCompiledTemplate('comp1', tmpl(`{{ num }}`))
const comp1 = codeSpace
.component('comp1')
.data(() => ({ num: 1 }))
.extraThisFieldsType<{ a: number; updateNum: (num: number) => void }>()
.lifetime('created', function () {
this.a = 1
this.updateNum = (num) => {
this.a = num
this.setData({ num })
}
})
.register()
codeSpace.addComponentStaticConfig('comp2', {
usingComponents: {
comp1: 'comp1',
},
})
codeSpace.addCompiledTemplate('comp2', tmpl(``))
codeSpace
.component('comp2')
.pageLifetime('show', function () {
const instance = this.selectComponent('#c1', comp1)
expect(instance).not.toBe(null)
expect(instance!.a).toBe(1)
instance!.updateNum(2)
expect(instance!.a).toBe(2)
})
.register()
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'comp2')
expect(domHtml(root.getComponent())).toBe('1')
root.getComponent().triggerPageLifetime('show', [])
expect(domHtml(root.getComponent())).toBe('2')
})
test('overall behavior', () => {
const env = new MiniProgramEnv()
const codeSpace = env.createCodeSpace('', true)
const componentSpace = codeSpace.getComponentSpace()
const overall = componentSpace.defineBehavior({
is: 'overall',
data: {
num: 1,
},
})
codeSpace.setOverallBehavior(overall)
codeSpace.addCompiledTemplate('comp', tmpl(`{{ num }}
`))
codeSpace.component('comp').register()
const ab = env.associateBackend()
const root = ab.createRoot('body', codeSpace, 'comp')
expect(domHtml(root.getComponent())).toBe('1
')
})
})