blob: e9eb7a3071cae88bbd111bb163585f8fb7882f6a [file]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import type {BookmarksPageState, NodeMap} from 'chrome://bookmarks/bookmarks.js';
import {createEmptyState, removeBookmark, Store, StoreClientMixinLit} from 'chrome://bookmarks/bookmarks.js';
import {CrLitElement, html} from 'chrome://resources/lit/v3_0/lit.rollup.js';
import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js';
import {assertDeepEquals, assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js';
import {microtasksFinished} from 'chrome://webui-test/test_util.js';
import {TestStore} from './test_store.js';
import {createFolder, createItem, getAllFoldersOpenState, testTree} from './test_util.js';
const TestStoreClientElementBase = StoreClientMixinLit(CrLitElement);
class TestStoreClientElement extends TestStoreClientElementBase {
static get is() {
return 'test-store-client';
}
override render() {
return html`
${this.toArray(this.items).map(item => html`
<div class="item">${item}</div>`)}
`;
}
static override get properties() {
return {
items: {type: Object},
};
}
accessor items: NodeMap = {};
hasChanged: boolean = false;
toArray(items: NodeMap) {
return Object.values(items).map(value => value.id);
}
override connectedCallback() {
super.connectedCallback();
this.updateFromStore();
}
override willUpdate(changedProperties: PropertyValues<this>) {
super.willUpdate(changedProperties);
if (changedProperties.has('items') &&
Object.values(this.items).length > 0) {
this.itemsChanged(this.items, changedProperties.get('items'));
}
}
override onStateChanged(state: BookmarksPageState) {
this.items = state.nodes || {};
}
itemsChanged(_newItems: NodeMap, oldItems?: NodeMap) {
if (oldItems && Object.values(oldItems).length > 0) {
this.hasChanged = true;
}
}
}
customElements.define(TestStoreClientElement.is, TestStoreClientElement);
suite('bookmarks.Store', function() {
let store: TestStore;
setup(function() {
const nodes = testTree(createFolder('1', [
createItem('11'),
createItem('12'),
createItem('13'),
]));
store = new TestStore({
nodes: nodes,
folderOpenState: getAllFoldersOpenState(nodes),
});
store.setReducersEnabled(true);
store.replaceSingleton();
});
test('batch mode disables updates', function() {
let lastStateChange: BookmarksPageState|null = null;
const observer = {
onStateChanged: function(state: BookmarksPageState) {
lastStateChange = state;
},
};
store.addObserver(observer);
store.beginBatchUpdate();
store.dispatch(removeBookmark('11', '1', 0, store.data.nodes));
assertEquals(null, lastStateChange);
store.dispatch(removeBookmark('12', '1', 0, store.data.nodes));
assertEquals(null, lastStateChange);
store.endBatchUpdate();
assertDeepEquals(['13'], lastStateChange!.nodes['1']!.children);
});
});
suite('bookmarks.StoreClientMixin', function() {
let store: Store;
let client: TestStoreClientElement;
function update(newState: BookmarksPageState): Promise<void> {
store.data = newState;
store.endBatchUpdate();
return microtasksFinished();
}
function getRenderedItems() {
return Array.from(client.shadowRoot.querySelectorAll('.item'))
.map((div) => div.textContent.trim());
}
setup(function() {
document.body.innerHTML = window.trustedTypes!.emptyHTML;
// Reset store instance:
Store.setInstance(new Store());
store = Store.getInstance();
const state = createEmptyState();
state.nodes = testTree(createFolder('1', [
createItem('11'),
createItem('12'),
createItem('13'),
]));
store.init(state);
client =
document.createElement('test-store-client') as TestStoreClientElement;
document.body.appendChild(client);
return microtasksFinished();
});
test('renders initial data', function() {
assertDeepEquals(['0', '1', '11', '12', '13'], getRenderedItems());
});
test('renders changes to watched state', async () => {
assertFalse(client.hasChanged);
const newItems = testTree(createFolder('1', [
createItem('11'),
createItem('12'),
]));
const newState = Object.assign({}, store.data, {
nodes: newItems,
});
await update(newState);
assertTrue(client.hasChanged);
assertDeepEquals(['0', '1', '11', '12'], getRenderedItems());
});
test('ignores changes to other subtrees', async () => {
const newState = Object.assign({}, store.data, {selectedFolder: 'foo'});
await update(newState);
assertFalse(client.hasChanged);
});
});