import { Component, component, html, update } from '../../src/fudgel.js';
@Component('show-prop', {
prop: ['prop'],
template: '{{prop}}',
})
class ShowProp {
prop = 'not yet replaced';
}
component('test-string', {
template: '',
});
component(
'test-async',
{
template: '',
},
class {
value = 'before-update';
onViewInit() {
setTimeout(() => (this.value = 'after-update'));
}
}
);
let trackInstance = 0;
@Component('test-scope-item', {
prop: ['prop'],
template: 'Item: {{propName}}',
})
class TestScopeItem {
prop;
propName = 'no prop set';
onChange() {
this.propName = this.prop ? this.prop.name : 'no prop set';
}
}
component(
'test-scope',
{
template: html``,
},
class TestScope {
list = [];
name = 'test-scope';
onInit() {
setTimeout(() => (this.list = [{ name: 'after-update' }]));
}
updateAll() {
// This function is exposed by Fudgel to redraw all components.
update();
}
updateList() {
this.list[0].name = 'updatedName';
this.list = [...this.list, { name: 'second-item' }];
}
updateName() {
// This updates a deeply nested property, which does not trigger a
// redraw.
this.list[0].name = 'updatedName';
// Only trigger an update of this one component, which also doesn't
// redraw the label.
update(this);
}
}
);
@Component('test-update-child', {
prop: ['childValue'],
template: '{{childValue}}',
})
class TestUpdateChildComponent {
childValue = 'initialValue';
}
@Component('test-update-parent', {
template:
'',
})
class TestUpdateParentComponent {
value = 'fromParent';
update() {
this.value = 'afterUpdate';
}
}
describe('prop', () => {
it('assigns a string property', () => {
cy.mount('');
cy.get('show-prop').should('have.text', 'some value');
});
it('shows updates to a class property', () => {
cy.mount('');
cy.get('show-prop').should('have.text', 'after-update');
});
it('shows items from a list', () => {
cy.mount('');
cy.get('test-scope-item').should('have.text', 'Item: after-update');
// Add a second item
cy.get('#updateList').click();
cy.get('test-scope-item').should(
'have.text',
'Item: after-updateItem: second-item'
);
// Update the first item and manually redraw, but this does not update
// the label.
cy.get('#updateName').click();
cy.get('test-scope-item').should(
'have.text',
'Item: after-updateItem: second-item'
);
// Update everything in all components
cy.get('#updateAll').click();
cy.get('test-scope-item').should(
'have.text',
'Item: updatedNameItem: second-item'
);
});
it('triggers onUpdate', () => {
cy.mount('');
cy.get('test-update-child').should('have.text', 'fromParent');
cy.get('button').click();
cy.get('test-update-child').should('have.text', 'afterUpdate');
});
});
@Component('delayed-child', {
prop: ['theString'],
style: `
:host {
display: block;
border: 1px solid black;
padding: 10px;
}
`,
template: '{{theString}}',
})
class DelayedChildComponent {}
@Component('delayed-parent', {
prop: ['theString'],
style: `
:host {
display: block;
border: 1px solid red;
padding: 10px;
}
`,
template: '',
})
class DelayedParentComponent {}
@Component('delayed-grandparent', {
template: `
- Value: {{theString}}
`,
})
class DelayedGrandparentComponent {
theString = 'initial';
update() {
this.theString = 'updated';
}
}
describe('delayed prop updates', () => {
it('updates a prop in a child component after the parent updates', () => {
cy.mount('');
cy.get('delayed-child').should('have.text', 'initial');
cy.get('button').click();
cy.get('delayed-child').should('have.text', 'updated');
});
});