| // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| library swarm_tests; |
| |
| import 'dart:html'; |
| import 'dart:async'; |
| import 'package:expect/expect.dart'; |
| import 'package:unittest/html_config.dart'; |
| import 'package:unittest/unittest.dart'; |
| import '../swarmlib.dart'; |
| import '../swarm_ui_lib/base/base.dart'; |
| import '../swarm_ui_lib/util/utilslib.dart'; |
| |
| // TODO(jmesserly): these would probably be easier to debug if they were written |
| // in the WebKit layout test style, so we could easy compare that the DOM is |
| // what we expect it to be after performing some simulated user actions. |
| |
| void main() { |
| useHtmlConfiguration(); |
| Swarm swarm = new Swarm(useCannedData: true); |
| UIStateProxy state = new UIStateProxy(swarm.sections); |
| swarm.state = state; |
| swarm.run(); |
| // TODO(jmesserly): should be adding the full stylesheet here |
| Dom.addStyle(''' |
| .story-content { |
| -webkit-column-width: 300px; |
| -webkit-column-gap: 26px; /* 2em */ |
| }'''); |
| |
| getStoryNode() => swarm.frontView.storyView.node; |
| |
| getView(Section section) { |
| return CollectionUtils.find( |
| swarm.frontView.sections.childViews, (view) => view.section == section); |
| } |
| |
| getHistory(Article article) { |
| final feed = article.dataSource; |
| return { |
| 'section': CollectionUtils |
| .find(swarm.sections, (s) => s.feeds.indexOf(feed, 0) >= 0) |
| .id, |
| 'feed': feed.id, |
| 'article': article.id |
| }; |
| } |
| |
| test('BackButton', () { |
| _serialInvokeAsync([ |
| () { |
| Expect.equals(null, swarm.frontView.storyView); // verify initial state |
| |
| // Make sure we've transitioned to the section |
| // In the real app, this isn't needed because ConveyorView fires the |
| // transition end event before we can click a story. |
| SectionView section = getView(swarm.sections[0]); |
| section.showSources(); |
| }, |
| () { |
| final item = swarm.sections[0].feeds[2].articles[1]; |
| state.loadFromHistory(getHistory(item)); |
| |
| Expect.equals(item, state.currentArticle.value); |
| |
| Expect.isFalse(getStoryNode().classes.contains(CSS.HIDDEN_STORY)); |
| |
| state.loadFromHistory({}); |
| |
| Expect.equals(null, state.currentArticle.value); |
| Expect.isTrue(getStoryNode().classes.contains(CSS.HIDDEN_STORY)); |
| } |
| ]); |
| }); |
| |
| test('StoryView', () { |
| state.clearHistory(); |
| |
| Expect.isTrue(getStoryNode().classes.contains(CSS.HIDDEN_STORY)); |
| |
| final dataSourceView = |
| swarm.frontView.currentSection.dataSourceView.getSubview(0); |
| final itemView = dataSourceView.itemsView.getSubview(0); |
| // TODO(jacobr): remove this null check. This is likely due to tests |
| // running without the correct CSS to size the window so that some items |
| // are visible. |
| if (itemView != null) { |
| click(itemView.node); |
| state.expectHistory([getHistory(itemView.item)]); |
| } |
| }); |
| |
| test('SliderMenu', () { |
| Expect.equals(getView(swarm.sections[0]), swarm.frontView.currentSection); |
| |
| // Find the first slider menu item, and click on the one next after it. |
| click(document.querySelectorAll('.${CSS.SM_ITEM}')[1]); |
| |
| Expect.equals(getView(swarm.sections[1]), swarm.frontView.currentSection); |
| |
| // Find the first menu item again and click on it. |
| click(document.querySelector('.${CSS.SM_ITEM}')); |
| |
| Expect.equals(getView(swarm.sections[0]), swarm.frontView.currentSection); |
| }); |
| } |
| |
| /** Triggers the click event, like [http://api.jquery.com/click/] */ |
| click(Element element) { |
| // TODO(rnystrom): This should be on the DOM API somewhere. |
| MouseEvent event = new MouseEvent('click'); |
| element.dispatchEvent(event); |
| } |
| |
| /** A proxy so we can intercept history calls */ |
| class UIStateProxy extends SwarmState { |
| List<Map<String, String>> history; |
| |
| UIStateProxy(Sections dataModel) : super(dataModel) { |
| clearHistory(); |
| } |
| |
| void pushToHistory() { |
| history.add(toHistory()); |
| super.pushToHistory(); |
| } |
| |
| void clearHistory() { |
| history = new List<Map<String, String>>(); |
| } |
| |
| void expectHistory(List<Map<String, String>> entries) { |
| Expect.equals(entries.length, history.length); |
| for (int i = 0; i < entries.length; i++) { |
| Map e = entries[i]; |
| Map h = history[i]; |
| Expect.equals(e['article'], h['article']); |
| } |
| clearHistory(); |
| } |
| } |
| |
| void _serialInvokeAsync(List closures) { |
| final length = closures.length; |
| if (length > 0) { |
| int i = 0; |
| void invokeNext() { |
| closures[i](); |
| i++; |
| if (i < length) { |
| Timer.run(expectAsync(invokeNext)); |
| } |
| } |
| |
| Timer.run(expectAsync(invokeNext)); |
| } |
| } |