Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

initial commit

  • Loading branch information...
commit 2439de854882041444645d087d8bcdebba64214f 0 parents
Luke Closs authored
5 Changes
@@ -0,0 +1,5 @@
+---
+version: 0.10
+date: Mon Mar 27 06:04:00 PST 2006
+changes:
+- Maiden voyage.
42 DESIGN
@@ -0,0 +1,42 @@
+=== Notes
+
+* Current takahashi:
+** Each slide's source separated by '----'
+** Each slide is turned into HTML
+
+=== Goals
+
+* Normal looking section uses current processing
+
+* Preprocess slide into javascript function
+* Each function returns HTML
+* Support a stash
+
+* $foo is stash variable
+* @foo is local variable
+* %foo is global/config variable
+
+* Support effects
+
+ %slide_effect = 'bleach'
+ %bullet_effect = 'slide_from_left'
+ %theme = 'dark.css'
+
+** Scriptaculous
+
+* To create a heredoc
+
+----
+$multiline = <end>
+
+<end>
+$two_lines =
+line1
+line2
+----
+$_ = $intro.replace(/\*/g, 'ø');
+----
+$_ .=
+* Next point
+** Foo
+** Bar
18 MANIFEST
@@ -0,0 +1,18 @@
+bin/render-template
+Changes
+config.yaml
+css/sporx.css
+DESIGN
+doc/html/Sporx.html
+doc/Makefile
+doc/pod/Sporx.pod
+doc/text/Sporx.text
+lib/sporx.js
+Makefile
+MANIFEST
+META.yml
+README
+slides/sporx.slides
+template/controls.xul
+template/license.html
+template/sporx.xul
7 META.yml
@@ -0,0 +1,7 @@
+---
+name: Sporx
+version: 0.10
+author:
+ - Ingy döt Net <ingy@cpan.org>
+abstract: Spork meets Takahashi
+license: mpl
28 Makefile
@@ -0,0 +1,28 @@
+.PHONY: all manifest dist doc
+
+ALL_T_HTML:=$(shell ls -1 slides/*.slides | perl -pe 's/slides$$/xul/;s/^.*\///')
+
+all: $(ALL_T_HTML)
+
+manifest: clean
+ find . -type f | perl -pe 's/..//' > MANIFEST
+
+dist: doc manifest META.yml
+ H=`pwd`; \
+ N=`perl -MYAML -e 'print((YAML::LoadFile("META.yml"))->{name})'`; \
+ V=`perl -MYAML -e 'print((YAML::LoadFile("META.yml"))->{version})'`; \
+ D="$${N}-$${V}"; \
+ rm -fr "/tmp/$$D"; \
+ cat MANIFEST | cpio -dump "/tmp/$$D"; \
+ cd /tmp; tar czvf "$${D}.tar.gz" $$D; rm -r $$D; \
+ cd $$H; mv "/tmp/$${D}.tar.gz" ./
+
+doc:
+ make -C doc
+
+%.xul: slides/%.slides template/* config.yaml
+ rm -f $@
+ perl bin/render-template $< $@
+
+clean purge:
+ -rm *.xul Sporx-*.tar.gz
27 README
@@ -0,0 +1,27 @@
+Luke Closs's Open Web Testing talk.
+
+
+Sporx (pronounced "Sporkahashi") is a mashup of Spork and Takahashi.
+
+See 'Changes' file for recent changes.
+
+INSTALLATION
+============
+
+Everything you need is in this folder.
+
+ tar xzf Sporx-0.xx.tar.gz
+ cd Sporx-0.xx
+ cp slides/sporx.slides slides/yourstuff.slides
+ vim yourstuff.slides # edit your slides
+ make yourstuff.xul # or simply: make
+ open yourstuff.xul # point your Firefox browser at the xul file
+
+AUTHORS
+=======
+
+Sporx was written by Ingy döt Net.
+
+Spork was written by Brian Ingerson.
+
+Takahashi was written by SHIMODA Hiroshi.
30 bin/render-template
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+
+use strict;
+use warnings;
+use Template;
+use IO::All;
+use YAML;
+
+my ($slides_path, $output_path) = @ARGV;
+
+my $t = Template->new(
+ {
+ INCLUDE_PATH => ['.', 'template/'],
+ }
+);
+
+my $config = YAML::LoadFile('config.yaml');
+my $main_template = $config->{main_template} || 'sporx.xul';
+
+my $data = {
+ %$config,
+ slides_content => io($slides_path)->all,
+};
+
+my $result;
+
+$t->process($main_template, $data, \$result) or die $t->error;
+
+unlink($output_path);
+io($output_path)->print($result);
4 config.yaml
@@ -0,0 +1,4 @@
+main_template: sporx.xul
+license_template: license.html
+css_location: css/sporx.css
+javascript_runtime: lib/sporx.js
223 css/sporx.css
@@ -0,0 +1,223 @@
+@charset "UTF-8";
+
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp>
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#canvas {
+ /*
+ color: black !important;
+ background: white !important;
+ */
+ color: #000 !important;
+ background: white !important;
+ /* font-weight: bold; */
+ font-family:
+ "Candara"
+ "Georgia"
+ "DejaVu Serif Condensed"
+ "Arial"
+ "Bitstream Vera Sans"
+ "Verdana"
+ "Apple LiGothic"
+ "Arial Black"
+ "Bitstream Vera Sans"
+ sans-serif !important;
+}
+#canvas * {
+ cursor: pointer !important;
+}
+#canvas image {
+ width: auto;
+ height: auto;
+}
+.link-text {
+ color: #000066 !important;
+ text-decoration: none !important;
+}
+.link-text:hover {
+ color: #3333FF !important;
+/* border-bottom: dotted 1px; */
+}
+.link-text:active {
+ color: #9999FF !important;
+}
+.s {
+ font-size: 33%;
+}
+.iu {
+ text-decoration: underline;
+ font-style: italic;
+}
+.ui {
+/* text-decoration: underline; */
+ font-style: italic;
+}
+.u {
+ text-decoration: underline;
+}
+.date {
+ font-style: italic;
+ text-decoration: underline;
+ font-size: 66%;
+}
+.i {
+ font-style: italic;
+ font-family: "Cambria"
+ "Times New Roman"
+ "Bitstream Vera Serif"
+ serif;
+}
+.t {
+ font-style: italic;
+}
+.tag {
+ color: #339933;
+}
+.att {
+ color: #333399;
+}
+.key {
+ color: #009999;
+}
+.h {
+ color: #000;
+ margin: 0px;
+}
+.b {
+ color: #000;
+ font-size: 66%;
+}
+.c {
+ color: #C39;
+ margin: 0px;
+}
+.m {
+ color: #963;
+ margin: 0px;
+ font-family: "Comic Sans MS";
+}
+.cz {
+ color: #C39;
+ margin: 0px;
+ font-family: "Candara";
+ margin-right: -10px;
+}
+.z {
+ margin: 0px;
+ margin-left: -10px;
+ font-family: "Candara"
+}
+.x {
+ color: #C00;
+ margin: 0px;
+}
+.xs {
+ color: #633;
+ margin: 0px;
+ text-decoration: line-through;
+}
+.ci {
+ color: #C39;
+ margin: 0px;
+ font-style: italic;
+ font-family: "Constantia"
+ "Times New Roman"
+ "Bitstream Vera Serif"
+ serif;
+}
+.cu {
+ color: #C39;
+ margin: 0px;
+ text-decoration: underline;
+}
+.ct {
+ color: #C39;
+ margin: 0px;
+ font-style: italic;
+}
+.hs {
+ color: #f33;
+ margin: 0px;
+ text-decoration: line-through;
+}
+.ht {
+ color: #aaa;
+ font-style: italic;
+}
+.pre {
+ font-family: "Consolas"
+ "Anonymous"
+ "Andale Mono"
+ "Bitstream Vera Sans Mono"
+ monospace;
+ padding-bottom: 8px;
+}
+#canvas[rendering="true"] image {
+ display: none;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+ color: white !important;
+}
+
+
+tabbox, tabpanels, tabpanel {
+ margin: 0;
+ padding: 0;
+}
+
+
+
+
+#canvas[eva="true"] {
+ background: white !important;
+ color: black !important;
+ font-family:
+ "Georgia"
+ "DejaVu Serif Condensed"
+ "Apple LiGothic"
+ "Arial Black"
+ serif !important;
+}
+#canvas[eva="true"] .link-text {
+ color: red !important;
+ text-decoration: none !important;
+}
+#canvas[eva="true"] .link-text:hover {
+ color: pink !important;
+}
+#canvas[eva="true"] .link-text:active {
+ color: orange !important;
+}
+#canvas[rendering="true"] *,
+#canvas[rendering="true"] .text-link {
+ color: black !important;
+}
+
+
+
+
+#canvasToolbar {
+ position: relative;
+}
+
20 doc/Makefile
@@ -0,0 +1,20 @@
+.PHONY: all clean
+
+NAME=Sporx
+
+SOURCE=pod/$(NAME).pod
+
+all: html/$(NAME).html text/$(NAME).text
+
+html/$(NAME).html: $(SOURCE) html
+ pod2html $< > $@
+ rm pod2htm*.tmp
+
+text/$(NAME).text: $(SOURCE) text
+ pod2text $< > $@
+
+html text:
+ mkdir -p $@
+
+clean:
+ rm -fr html text
61 doc/html/Sporx.html
@@ -0,0 +1,61 @@
+<?xml version="1.0" ?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<title>Sporx - Spork meets Takahashi</title>
+<meta http-equiv="content-type" content="text/html; charset=utf-8" />
+<link rev="made" href="mailto:_www@b02.apple.com" />
+</head>
+
+<body style="background-color: white">
+
+<p><a name="__index__"></a></p>
+<!-- INDEX BEGIN -->
+
+<ul>
+
+ <li><a href="#name">NAME</a></li>
+ <li><a href="#synopsis">SYNOPSIS</a></li>
+ <li><a href="#description">DESCRIPTION</a></li>
+ <li><a href="#author">AUTHOR</a></li>
+ <li><a href="#copyright">COPYRIGHT</a></li>
+</ul>
+<!-- INDEX END -->
+
+<hr />
+<p>
+</p>
+<h1><a name="name">NAME</a></h1>
+<p>Sporx - Spork meets Takahashi</p>
+<p>
+</p>
+<hr />
+<h1><a name="synopsis">SYNOPSIS</a></h1>
+<pre>
+ &gt; vim slides/MyShow.slides
+ &gt; make
+ &gt; open MyShow.xul</pre>
+<p>
+</p>
+<hr />
+<h1><a name="description">DESCRIPTION</a></h1>
+<p>Sporx (pronounced ``Sporkahashi'') is a mashup of the best ideas from
+CPAN's Spork and the XUL's Takahashi Method slideshow presentation
+softwares.</p>
+<p>
+</p>
+<hr />
+<h1><a name="author">AUTHOR</a></h1>
+<p>Ingy döt Net &lt;<a href="mailto:ingy@cpan.org">ingy@cpan.org</a>&gt;</p>
+<p>
+</p>
+<hr />
+<h1><a name="copyright">COPYRIGHT</a></h1>
+<p>Copyright (c) 2006. Ingy döt Net. All rights reserved.</p>
+<p>This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.</p>
+<p>See <a href="http://www.perl.com/perl/misc/Artistic.html">http://www.perl.com/perl/misc/Artistic.html</a></p>
+
+</body>
+
+</html>
30 doc/pod/Sporx.pod
@@ -0,0 +1,30 @@
+=head1 NAME
+
+Sporx - Spork meets Takahashi
+
+=head1 SYNOPSIS
+
+ > vim slides/MyShow.slides
+ > make
+ > open MyShow.xul
+
+=head1 DESCRIPTION
+
+Sporx (pronounced "Sporkahashi") is a mashup of the best ideas from
+CPAN's Spork and the XUL's Takahashi Method slideshow presentation
+softwares.
+
+=head1 AUTHOR
+
+Ingy döt Net <ingy@cpan.org>
+
+=head1 COPYRIGHT
+
+Copyright (c) 2006. Ingy döt Net. All rights reserved.
+
+This program is free software; you can redistribute it and/or modify it
+under the same terms as Perl itself.
+
+See L<http://www.perl.com/perl/misc/Artistic.html>
+
+=cut
24 doc/text/Sporx.text
@@ -0,0 +1,24 @@
+NAME
+ Sporx - Spork meets Takahashi
+
+SYNOPSIS
+ > vim slides/MyShow.slides
+ > make
+ > open MyShow.xul
+
+DESCRIPTION
+ Sporx (pronounced "Sporkahashi") is a mashup of the best ideas from
+ CPAN's Spork and the XUL's Takahashi Method slideshow presentation
+ softwares.
+
+AUTHOR
+ Ingy döt Net <ingy@cpan.org>
+
+COPYRIGHT
+ Copyright (c) 2006. Ingy döt Net. All rights reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the same terms as Perl itself.
+
+ See <http://www.perl.com/perl/misc/Artistic.html>
+
493 lib/sporx.js
@@ -0,0 +1,493 @@
+var Presentation = {
+ init : function(option){
+ this.size = 9;
+
+ this._offset = 0;
+ this.canvas = document.getElementById('canvas');
+ this.content = document.getElementById('content');
+ this.textbox = document.getElementById('textField');
+ this.deck = document.getElementById('deck');
+ this.scroller = document.getElementById('scroller');
+
+ this.toolbar = document.getElementById('canvasToolbar');
+ this.toolbarHeight = this.toolbar.boxObject.height;
+ this.isToolbarHidden = true;
+ this.toolbar.setAttribute('style', 'margin-top:'+(0-this.toolbarHeight)+'px;margin-bottom:0px;');
+
+ if(option){
+ for(var i in option){this[i] = option[i]}
+ }
+
+ if (this.readParameter()) {
+ this.takahashi();
+ }
+
+ document.documentElement.focus();
+ },
+
+ takahashi : function(){
+ if (!document.title)
+ document.title = this.data[0].replace(/[\r\n]/g, ' ');
+
+ if(!this.data[this.offset]){
+ this.offset = this.data.length-1;
+ }
+ document.getElementById("current_page").value = this.offset+1;
+ document.getElementById("max_page").value = this.data.length;
+
+ this.scroller.setAttribute('maxpos', this.data.length-1);
+ this.scroller.setAttribute('curpos', this.offset);
+
+ var broadcaster = document.getElementById('canBack');
+ if (!this.offset)
+ broadcaster.setAttribute('disabled', true);
+ else
+ broadcaster.removeAttribute('disabled');
+
+ var broadcaster = document.getElementById('canForward');
+ if (this.offset == this.data.length-1)
+ broadcaster.setAttribute('disabled', true);
+ else
+ broadcaster.removeAttribute('disabled');
+
+ this.canvas.setAttribute('rendering', true);
+
+ var text = this.data[this.offset].
+ replace(/^[\r\n]+/g,"").replace(/[\r\n]+$/g,"").replace(/(\r\n|[\r\n])/g,"\n")
+ .split('\n');
+ var range = document.createRange();
+ range.selectNodeContents(this.content);
+ range.deleteContents();
+ range.detach();
+
+ var line;
+ var newLine;
+ var uri;
+ var image_width;
+ var image_total_width = 0;
+ var image_height;
+ var image_total_height = 0;
+ var image_src;
+
+ var labelId = 0;
+
+ for (var i = 0; i < text.length; i++)
+ {
+ this.content.appendChild(document.createElement('hbox'));
+ this.content.lastChild.setAttribute('align', 'center');
+ this.content.lastChild.setAttribute('pack', 'center');
+
+ line = text[i];
+ image_width = 0;
+ image_height = 0;
+
+ if (line.match(/^ /)) {
+ this.content.lastChild.setAttribute('align', 'left');
+ this.content.lastChild.setAttribute('class', 'pre');
+ line = line.substring(1)
+ }
+
+ while (line.match(/^([^\{]+)?(\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}|\{\{(([^\|]+)?\||)(.+?)\}\})(.+)?/))
+ {
+ if (RegExp.$1) {
+ this.content.lastChild.appendChild(document.createElement('description'));
+ this.content.lastChild.lastChild.setAttribute('value', RegExp.$1);
+ }
+ newLine = line.substring((RegExp.$1+RegExp.$2).length);
+
+ // Images
+ if (/^([^\{]+)?\{\{ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\}]*\}\}/.test(line)) {
+ this.content.lastChild.appendChild(document.createElement('image'));
+ image_src = RegExp.$2;
+ if (image_src.indexOf('http://') < 0 &&
+ image_src.indexOf('https://') < 0)
+ image_src = this.dataFolder+image_src;
+ this.content.lastChild.lastChild.setAttribute('src', image_src);
+ this.content.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
+ this.content.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
+ image_width += parseInt(RegExp.$3 || '0');
+ image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
+ }
+
+ // Styles
+ // else if (/^([^\{]+)?\{\{#([^\|]+)\|([^\}]+)\}\}/.test(line)) {
+ else if (/^([^\{]+)?\{\{(#([^\|]+)?\|)(.+?)\}\}/.test(line)) {
+ uri = RegExp.$4;
+ this.content.lastChild.appendChild(document.createElement('description'));
+ this.content.lastChild.lastChild.setAttribute('value', uri);
+ this.content.lastChild.lastChild.setAttribute('class', RegExp.$3);
+ }
+
+ // Links
+ else if (/^([^\{]+)?\{\{(([^\|]+)?\||)([^\}]+)\}\}/.test(line)) {
+ uri = RegExp.$4;
+ if (uri.indexOf('://') < 0)
+ uri = this.dataFolder+uri;
+ this.content.lastChild.appendChild(document.createElement('description'));
+ this.content.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
+ this.content.lastChild.lastChild.setAttribute('href', uri);
+ this.content.lastChild.lastChild.setAttribute('tooltiptext', uri);
+ this.content.lastChild.lastChild.setAttribute('statustext', uri);
+ this.content.lastChild.lastChild.setAttribute('class', 'link-text');
+ }
+
+ line = newLine;
+ }
+
+ if (line) {
+ this.content.lastChild.appendChild(document.createElement('description'));
+ this.content.lastChild.lastChild.setAttribute('value', line);
+ }
+
+ image_total_width = Math.max(image_total_width, image_width);
+ image_total_height += image_height;
+ }
+
+ this.content.setAttribute('style', 'font-size:10px;');
+
+ if (this.content.boxObject.width) {
+ var canvas_w = this.canvas.boxObject.width;
+ var canvas_h = this.canvas.boxObject.height-image_total_height;
+
+ var content_w = this.content.boxObject.width;
+ var new_fs = Math.round((canvas_w/content_w) * this.size);
+ this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+
+ if (this.content.boxObject.width < image_total_width) {
+ content_w = image_total_width;
+ new_fs = Math.round((canvas_w/content_w) * this.size);
+ this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+ }
+
+ var content_h = this.content.boxObject.height;
+ if(content_h >= canvas_h){
+ content_h = this.content.boxObject.height;
+ new_fs = Math.round((canvas_h/content_h) * new_fs);
+ this.content.setAttribute('style', 'font-size:'+ new_fs + "px");
+ }
+ }
+
+ this.canvas.removeAttribute('rendering');
+ },
+
+ reload : function() {
+ if (this.dataPath != location.href) {
+ var path = this.dataPath;
+ if (location.href.match(/^https?:/)) {
+ var request = new XMLHttpRequest();
+ request.open('GET', path);
+ request.onload = function() {
+ Presentation.textbox.value = request.responseText;
+ Presentation.data = Presentation.textbox.value.split('----');
+
+ Presentation.takahashi();
+
+ path = null;
+ request = null;
+ };
+ request.send(null);
+ }
+ else {
+ document.getElementById('dataLoader').setAttribute('src', 'about:blank');
+ window.setTimeout(function() {
+ document.getElementById('dataLoader').setAttribute('src', path);
+ path = null;
+ }, 10);
+ }
+ }
+ else
+ window.location.reload();
+ },
+
+ forward : function(){
+ this.offset++;
+ this.takahashi();
+ },
+ back : function(){
+ this.offset--;
+ if(this.offset < 0){this.offset = 0}
+ this.takahashi();
+ },
+ home : function(){
+ this.offset = 0;
+ this.takahashi();
+ },
+ end : function(){
+ this.offset = this.data.length-1;
+ this.takahashi();
+ },
+ showPage : function(aPageOffset){
+ this.offset = aPageOffset ? aPageOffset : 0 ;
+ this.takahashi();
+ },
+
+ addPage : function() {
+ if (this.textbox.value &&
+ !this.textbox.value.match(/(\r\n|[\r\n])$/))
+ this.textbox.value += '\n';
+ this.textbox.value += '----\n';
+ this.onEdit();
+ },
+
+ toggleEditMode : function(){
+ this.deck.selectedIndex = (this.deck.selectedIndex == 0) ? 1 : 0 ;
+ },
+ toggleEvaMode : function(){
+ var check = document.getElementById('toggleEva');
+ if (this.canvas.getAttribute('eva') == 'true') {
+ this.canvas.removeAttribute('eva');
+ check.checked = false;
+ }
+ else {
+ this.canvas.setAttribute('eva', true);
+ check.checked = true;
+ }
+ },
+
+ onPresentationClick : function(aEvent){
+ if (!this.isToolbarHidden)
+ this.showHideToolbar();
+
+ switch(aEvent.button)
+ {
+ case 0:
+ var uri = aEvent.target.getAttribute('href');
+ if (uri)
+ window.open(uri);
+ else {
+ this.forward();
+ document.documentElement.focus();
+ }
+ break;
+ case 2:
+ this.back();
+ document.documentElement.focus();
+ break;
+ default:
+ break;
+ }
+ },
+ onScrollerDragStart : function(){
+ this.scroller.dragging = true;
+ },
+ onScrollerDragMove : function(){
+ if (this.scroller.dragging)
+ this.showPage(parseInt(this.scroller.getAttribute('curpos')));
+ },
+ onScrollerDragDrop : function(){
+ if (this.scroller.dragging) {
+ this.showPage(parseInt(this.scroller.getAttribute('curpos')));
+ }
+ this.scroller.dragging = false;
+ },
+ onEdit : function() {
+ this.data = this.textbox.value.split('----');
+ this.takahashi();
+ },
+
+ onKeyPress : function(aEvent) {
+ switch(aEvent.keyCode)
+ {
+ case aEvent.DOM_VK_BACK_SPACE:
+ if (this.isPresentationMode) {
+ aEvent.preventBubble();
+ aEvent.preventDefault();
+ Presentation.back();
+ }
+ break;
+ default:
+ break;
+ }
+ },
+
+
+ onToolbarArea : false,
+ toolbarHeight : 0,
+ toolbarDelay : 300,
+ toolbarTimer : null,
+ isToolbarHidden : false,
+ onMouseMoveOnCanvas : function(aEvent) {
+ if (this.scroller.dragging) return;
+
+ this.onToolbarArea = (aEvent.clientY < this.toolbarHeight);
+
+ if (this.isToolbarHidden == this.onToolbarArea) {
+ if (this.toolbarTimer) window.clearTimeout(this.toolbarTimer);
+ this.toolbarTimer = window.setTimeout('Presentation.onMouseMoveOnCanvasCallback()', this.toolbarDelay);
+ }
+ },
+ onMouseMoveOnCanvasCallback : function() {
+ if (this.isToolbarHidden == this.onToolbarArea)
+ this.showHideToolbar();
+ },
+
+ toolbarAnimationDelay : 100,
+ toolbarAnimationSteps : 5,
+ toolbarAnimationInfo : null,
+ toolbarAnimationTimer : null,
+ showHideToolbar : function()
+ {
+ if (this.toolbarAnimationTimer) window.clearTimeout(this.toolbarAnimationTimer);
+
+ this.toolbarAnimationInfo = { count : 0 };
+ if (this.isToolbarHidden) {
+ this.toolbarAnimationInfo.start = 0;
+ this.toolbarAnimationInfo.end = this.toolbarHeight;
+ }
+ else {
+ this.toolbarAnimationInfo.start = this.toolbarHeight;
+ this.toolbarAnimationInfo.end = 0;
+ }
+ this.toolbarAnimationInfo.current = 0;
+
+ this.toolbar.setAttribute('style', 'margin-top:'+(0-(this.toolbarHeight-this.toolbarAnimationInfo.start))+'px; margin-bottom:'+(0-this.toolbarAnimationInfo.start)+'px;');
+
+ this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
+ },
+ animateToolbar : function()
+ {
+ this.toolbarAnimationInfo.current += parseInt(this.toolbarHeight/this.toolbarAnimationSteps);
+
+ var top, bottom;
+ if (this.toolbarAnimationInfo.start < this.toolbarAnimationInfo.end) {
+ top = this.toolbarHeight-this.toolbarAnimationInfo.current;
+ bottom = this.toolbarAnimationInfo.current;
+ }
+ else {
+ top = this.toolbarAnimationInfo.current;
+ bottom = this.toolbarHeight-this.toolbarAnimationInfo.current;
+ }
+
+ top = Math.min(Math.max(top, 0), this.toolbarHeight);
+ bottom = Math.min(Math.max(bottom, 0), this.toolbarHeight);
+
+ this.toolbar.setAttribute('style', 'margin-top:'+(0-top)+'px; margin-bottom:'+(0-bottom)+'px');
+
+ if (this.toolbarAnimationInfo.count < this.toolbarAnimationSteps) {
+ this.toolbarAnimationInfo.count++;
+ this.toolbarAnimationTimer = window.setTimeout('Presentation.animateToolbar()', this.toolbarAnimationDelay/this.toolbarAnimationSteps);
+ }
+ else
+ this.isToolbarHidden = !this.isToolbarHidden;
+ },
+
+
+
+ get offset(){
+ return this._offset;
+ },
+ set offset(aValue){
+ this._offset = parseInt(aValue || 0);
+ document.documentElement.setAttribute('lastoffset', this.offset);
+ return this.offset;
+ },
+
+ get data(){
+ if (!this._data) {
+ // Make sure you break the text into parts smaller than 4096
+ // characters, and name them as indicated. Tweak as required.
+ // (What a hack. A JS programmer should find a better way.)
+ // Luc St-Louis, and email is lucs@pobox.com.
+
+ nodes = document.getElementById('builtinCode').childNodes;
+ content = '';
+ for (i in nodes) {
+ if (nodes[i].nodeValue) {
+ content = content + nodes[i].nodeValue;
+ }
+ }
+
+ this._data = content.split("----");
+ }
+
+ return this._data;
+ },
+ set data(aValue){
+ this._data = aValue;
+ return aValue;
+ },
+
+
+ get isPresentationMode(){
+ return (this.deck.selectedIndex == 0);
+ },
+
+
+ get dataPath(){
+ if (!this._dataPath)
+ this.dataPath = location.href;
+ return this._dataPath;
+ },
+ set dataPath(aValue){
+ var oldDataPath = this._dataPath;
+ this._dataPath = aValue;
+ if (oldDataPath != aValue) {
+ this._dataFolder = this._dataPath.split('?')[0].replace(/[^\/]+$/, '');
+ }
+ return this._dataPath;
+ },
+
+ get dataFolder(){
+ if (!this._dataFolder)
+ this.dataPath = this.dataPath;
+ return this._dataFolder;
+ },
+ set dataFolder(aValue){
+ this._dataFolder = aValue;
+ return this._dataFolder;
+ },
+
+ readParameter : function() {
+ if (location.search) {
+ var param = location.search.replace(/^\?/, '');
+
+ if (param.match(/page=([0-9]+)/i))
+ this.offset = parseInt(RegExp.$1)-1;
+
+ if (param.match(/edit=(1|true|yes)/i))
+ this.toggleEditMode();
+
+ if (param.match(/eva=(1|true|yes)/i))
+ this.toggleEvaMode();
+
+ if (param.match(/data=([^&;]+)/i)) {
+ var path = unescape(RegExp.$1);
+ this.dataPath = path;
+ if (location.href.match(/^https?:/)) {
+ var request = new XMLHttpRequest();
+ request.open('GET', path);
+ request.onload = function() {
+ Presentation.textbox.value = request.responseText;
+ Presentation.data = Presentation.textbox.value.split('----');
+
+ Presentation.takahashi();
+ };
+ request.send(null);
+ }
+ else {
+ document.getElementById('dataLoader').setAttribute('src', path);
+ }
+ return false;
+ }
+ }
+ return true;
+ },
+ onDataLoad : function() {
+ if (!window.frames[0].document.body.hasChildNodes()) return;
+ var data = window.frames[0].document.body.firstChild.innerHTML;
+ if (!data) return;
+
+ this.textbox.value = data;
+ this.data = this.textbox.value.split('----');
+
+ this.takahashi();
+ }
+};
+
+function init()
+{
+ window.removeEventListener('load', init, false);
+
+ Presentation.init();
+}
+window.addEventListener('load', init, false);
298 slides/web-testing.slides
@@ -0,0 +1,298 @@
+Open Web Testing
+{{#c|☻}}{{#t|Luke Closs}}{{#c|☻}}
+----
+Brought
+to you by:
+----
+℧ℕℹⅭↀↁℰ
+{{#s|(Totally gratuitous)}}
+----
+And the
+Sporxahashi
+Method
+----
+Thank you
+Ingy Döt Net
+----
+{{#h|Agenda:}}
+ {{#b|➸ Theory}}
+ {{#b|➸ Examples}}
+ {{#b|➸ Questions}}
+----
+My Automation
+Background
+ ➸ Cellular ☏ {{#b|Telos}}
+ ➸ Email {{#b|ActiveState/Sophos}}
+ ➸ Web {{#b|Socialtext}}
+----
+{{#c|Terms}}
+----
+Manual
+Test
+----
+Unit
+Test
+----
+ ➸ Automation (A8N)
+ ➸ Integration Test
+ ➸ System Test
+----
+{{#c|Goal}}
+----
+Provide info about the
+{{#t|state of the software}}
+to decision makers
+----
+{{#c|Historical}}
+{{#c|Context}}
+----
+{{#c|Long time ago}}
+ {{#b|➸ Desktop apps}}
+----
+☝ Proprietary Tools
+----
+{{#c|Web 1.0}}
+ {{#b|➸ Browsing, Forms}}
+----
+☝ Scripts!
+----
+{{#c|Web 1.5}}
+ {{#b|➸ AJAX, Javascript}}
+----
+☝ Selenium
+----
+{{#c|Web 2.0}}
+ {{#b|➸ Web, HTTP, RSS, SMTP, Jabber, ...}}
+----
+☝ BDD?
+----
+Test the value
+to the business.
+----
+End result
+{{#b|aka}}
+Black box
+----
+{{#c|✍Tools☂}}
+----
+Choose a tool
+that fits your
+context
+----
+Example Toolchains
+----
+{{#c|"Ruby Style"}}
+ {{#b|➸ Cucumber}}
+ {{#b|➸ Written by devs}}
+----
+{{#att|Scenario:}} Add two numbers
+ {{#tag|Given}} I have entered 50
+ {{#tag|And}} I have entered 70
+ {{#tag|When}} I press add
+ {{#tag|Then}} The result should be 120
+----
+{{#c|"Sophos Style"}}
+ {{#b|➸ YAML}}
+ {{#b|➸ Test::A8N}}
+ {{#b|➸ Written by QA}}
+----
+ NAME: Admin changes their timezone
+ ID: admin_changes_tz
+ SUMMARY: Admins need to change their timezone.
+----
+ PRECONDITIONS:
+ - ensure user exists: admin
+ - ensure timezone is: America/Vancouver
+----
+ INSTRUCTIONS:
+ - login:
+ username: admin
+ password: testpass
+ - goto page: Account Settings
+ - verify current timezone is: America/Vancouver
+ - change timezone to: Australia/Brisbane
+ - verify current timezone is: Australia/Brisbane
+----
+ POSTCONDITIONS:
+ - ensure timezone is: America/Vancouver
+----
+{{#c|"Wikitest Style"}}
+ {{#b|➸ Wiki Tables}}
+ {{#b|➸ Keyword Driven}}
+ {{#b|➸ Based on Selenese}}
+ {{#b|➸ Written by Dev and QA}}
+----
+ {{#pre|| open | /login |}}
+ {{#pre|| title-is | Awesometown |}}
+ {{#pre|| text-like | //body | Welcome to Awesometown |}}
+----
+{{#c|Key Points}}
+----
+No contitionals
+or looping
+----
+Insulate Test Logic
+from {{#i|Test code}}
+----
+Risk Management
+----
+So we can
+☾ ✧ ☄
+sleep well
+----
+{{#c|Remember:}}
+There are no
+"Best Practices"
+----
+{{#c|Just:}}
+Better or Worse
+{{#i|for a given context}}
+----
+{{#c|5 Guidelines}}
+----
+❶ {{#i|Keep Up}}
+with development
+----
+❷ Make Tradeoffs
+{{#i|with intention}}
+----
+❸ Do the best
+{{#i|with what you have}}
+----
+Be resourceful
+with your team
+----
+Put people in a
+position they get
+excited about
+----
+❹ Balanced
+Breakfast
+----
+❺ Pay
+Attention
+----
+Periodical
+Reflection
+----
+Refactor
+your tests!
+----
+A8N costs $$$
+(So be pragmatic)
+----
+Questions‽
+----
+{{#c|Practical}}
+{{#c|Section}}
+----
+{{#c|OR:}} How our
+Breakfast
+has changed:
+----
+{{#c|Startup Time}}
+ 1 QA
+----
+Unit Tests
+Manual Testing
+Dogfood
+----
+{{#c|Dawn of Selenium}}
+ 1.5 QA
+----
+Selenium IDE
+ ☺ Easy to record
+ ☹ Hard to do anything else
+----
+Non-technical staff
+can write tests
+(but limiting!)
+----
+{{#c|Wikitest}}
+{{#c|Revolution}}
+----
+Built on Selenese
+ {{#b|➽ abstraction}}
+ {{#b|➽ less duplication}}
+ {{#b|➽ standardization}}
+----
+Keyword
+driven
+testing
+{{#s|FTW!}}
+----
+Express Tests
+in a Wiki Table
+----
+{{image src="wikitests.png" width="1234" height="392"}}
+----
+Suits the Team
+ {{#b|➺ Dogfood}}
+ {{#b|➺ Simple edit interface}}
+ {{#b|➺ Low barrier}}
+----
+Read the wiki table
+Execute the commands
+Produce results page
+----
+{{#c|Industrial}}
+Wikitest
+{{#c|Revolution}}
+----
+Interns++
+----
+Jump to 6,000
+test steps
+----
+A8N lags
+Development
+----
+But ...
+----
+No more
+regressions!
+----
+Overheard:
+{{#b|❝When was the last}}
+{{#b|bug we shipped?❞}}
+{{#s|(nobody knew)}}
+----
+{{#c|The Great}}
+{{#c|Depression}}
+{{#b|(QA layoffs)}}
+----
+Team loses QA
+
+{{#i|What to do?}}
+----
+{{#c|Answer:}}
+Change our
+practice
+----
+{{#c|Team agrees:}}
+Devs will write
+Sunny day A8N
+----
+Make the best
+out of what
+we have.
+----
+QA can focus
+on exceptions
+----
+Dev can write
+good A8N +
+Infrastructure
+----
+WIN-WIN-WIN
+----
+EOM
+----
+☃ Questions⁇ ☃
+----
+Links
+ ☑ {{#b|http://ingy.net}}
+ ♘ {{#b|http://cukes.info}}
+ ♨ {{#b|http://tinyurl.com/wikitests}}
+ ✈ {{#b|/sporx/}}
+ ♽ {{#b|/Test::A8N/}}
86 template/controls.xul
@@ -0,0 +1,86 @@
+<deck flex="1" id="deck">
+ <vbox flex="1" onmousemove="Presentation.onMouseMoveOnCanvas(event);">
+ <toolbox id="canvasToolbar">
+ <toolbar>
+ <toolbarbutton oncommand="Presentation.home()" label="|&lt;&lt;" observes="canBack"/>
+ <toolbarbutton oncommand="Presentation.back()" label="&lt;" observes="canBack"/>
+ <toolbarbutton oncommand="Presentation.forward()" label="&gt;" observes="canForward"/>
+ <toolbarbutton oncommand="Presentation.end()" label="&gt;&gt;|" observes="canForward"/>
+ <toolbarseparator/>
+ <hbox align="center">
+ <textbox id="current_page" size="4" oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/>
+ <description value="/"/>
+ <description id="max_page"/>
+ </hbox>
+ <toolbarseparator/>
+ <vbox flex="2">
+ <spacer flex="1"/>
+ <scrollbar id="scroller" align="center" orient="horizontal" oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" onmousedown="Presentation.onScrollerDragStart();" onmousemove="Presentation.onScrollerDragMove();" onmouseup="Presentation.onScrollerDragDrop();"/>
+ <spacer flex="1"/>
+ </vbox>
+ <toolbarseparator/>
+ <spacer flex="1"/>
+ <toolbarseparator/>
+ <toolbarbutton id="toggleEva" label="Eva" type="checkbox" autoCheck="false" oncommand="Presentation.toggleEvaMode();"/>
+ <toolbarseparator/>
+ <toolbarbutton label="Edit" oncommand="Presentation.toggleEditMode();"/>
+ <toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
+ </toolbar>
+ </toolbox>
+ <vbox flex="1" id="canvas" onclick="Presentation.onPresentationClick(event);">
+ <spacer flex="1"/>
+ <hbox flex="1">
+ <spacer flex="1"/>
+ <vbox id="content"/>
+ <spacer flex="1"/>
+ </hbox>
+ <spacer flex="1"/>
+ </vbox>
+ </vbox>
+ <vbox flex="1" id="edit">
+ <toolbox>
+ <toolbar>
+ <toolbarbutton label="New Page" oncommand="Presentation.addPage()"/>
+ <spacer flex="1"/>
+ <toolbarseparator/>
+ <toolbarbutton label="View" oncommand="Presentation.toggleEditMode();"/>
+ <toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
+ </toolbar>
+ </toolbox>
+ <textbox id="textField" flex="1" multiline="true" oninput="Presentation.onEdit()"/>
+ <hbox collapsed="true">
+ <iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/>
+ </hbox>
+ </vbox>
+</deck>
+
+<broadcasterset>
+ <broadcaster id="canBack"/>
+ <broadcaster id="canForward"/>
+</broadcasterset>
+
+<commandset>
+ <command id="cmd_forward" oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/>
+ <command id="cmd_back" oncommand="if (Presentation.isPresentationMode) Presentation.back();"/>
+ <command id="cmd_home" oncommand="if (Presentation.isPresentationMode) Presentation.home();"/>
+ <command id="cmd_end" oncommand="if (Presentation.isPresentationMode) Presentation.end();"/>
+</commandset>
+
+<keyset>
+ <key keycode="VK_ENTER" command="cmd_forward"/>
+ <key keycode="VK_RETURN" command="cmd_forward"/>
+ <key keycode="VK_PAGE_DOWN" command="cmd_forward"/>
+ <key keycode="VK_RIGHT" command="cmd_forward"/>
+ <key keycode="VK_DOWN" command="cmd_forward"/>
+ <!--key keycode="VK_BACK_SPACE" command="cmd_back"/-->
+ <key keycode="VK_UP" command="cmd_back"/>
+ <key keycode="VK_PAGE_UP" command="cmd_back"/>
+ <!--<key keycode="VK_BACK_UP" command="cmd_back"/>-->
+ <!--<key keycode="VK_BACK_LEFT" command="cmd_back"/>-->
+ <key keycode="VK_HOME" command="cmd_home"/>
+ <!--<key keycode="VK_END" command="cmd_end"/>-->
+ <key key="n" modifiers="accel" oncommand="Presentation.addPage();"/>
+ <key key="r" modifiers="accel" oncommand="window.location.reload();"/>
+ <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/>
+ <key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/>
+</keyset>
22 template/license.html
@@ -0,0 +1,22 @@
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+ -
+ - The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ - Portions created by the Initial Developer are Copyright (C) 2005
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp>
+ -
+ - ***** END LICENSE BLOCK ***** -->
19 template/sporx.xul
@@ -0,0 +1,19 @@
+[%- DEFAULT css_location='css/sporx.css' -%]
+[%- DEFAULT javascript_runtime='lib/sporx.js' -%]
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="[% css_location %]" type="text/css"?>
+
+<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);">
+
+<html:textarea id="builtinCode" style="visibility: collapse">
+[% slides_content %]
+</html:textarea>
+
+[% INCLUDE controls.xul %]
+
+<script src="[% javascript_runtime %]" type="application/x-javascript" />
+
+</page>
+
+[% INCLUDE $license_template %]
423 web-testing.xul
@@ -0,0 +1,423 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="css/sporx.css" type="text/css"?>
+
+<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="presentation" xmlns:html="http:/www.w3.org/1999/xhtml" orient="vertical" onkeypress="Presentation.onKeyPress(event);">
+
+<html:textarea id="builtinCode" style="visibility: collapse">
+Open Web Testing
+{{#c|☻}}{{#t|Luke Closs}}{{#c|☻}}
+----
+Brought
+to you by:
+----
+℧ℕℹⅭↀↁℰ
+{{#s|(Totally gratuitous)}}
+----
+And the
+Sporxahashi
+Method
+----
+Thank you
+Ingy Döt Net
+----
+{{#h|Agenda:}}
+ {{#b|➸ Theory}}
+ {{#b|➸ Examples}}
+ {{#b|➸ Questions}}
+----
+My Automation
+Background
+ ➸ Cellular ☏ {{#b|Telos}}
+ ➸ Email {{#b|ActiveState/Sophos}}
+ ➸ Web {{#b|Socialtext}}
+----
+{{#c|Terms}}
+----
+Manual
+Test
+----
+Unit
+Test
+----
+ ➸ Automation (A8N)
+ ➸ Integration Test
+ ➸ System Test
+----
+{{#c|Goal}}
+----
+Provide info about the
+{{#t|state of the software}}
+to decision makers
+----
+{{#c|Historical}}
+{{#c|Context}}
+----
+{{#c|Long time ago}}
+ {{#b|➸ Desktop apps}}
+----
+☝ Proprietary Tools
+----
+{{#c|Web 1.0}}
+ {{#b|➸ Browsing, Forms}}
+----
+☝ Scripts!
+----
+{{#c|Web 1.5}}
+ {{#b|➸ AJAX, Javascript}}
+----
+☝ Selenium
+----
+{{#c|Web 2.0}}
+ {{#b|➸ Web, HTTP, RSS, SMTP, Jabber, ...}}
+----
+☝ BDD?
+----
+Test the value
+to the business.
+----
+End result
+{{#b|aka}}
+Black box
+----
+{{#c|✍Tools☂}}
+----
+Choose a tool
+that fits your
+context
+----
+Example Toolchains
+----
+{{#c|"Ruby Style"}}
+ {{#b|➸ Cucumber}}
+ {{#b|➸ Written by devs}}
+----
+{{#att|Scenario:}} Add two numbers
+ {{#tag|Given}} I have entered 50
+ {{#tag|And}} I have entered 70
+ {{#tag|When}} I press add
+ {{#tag|Then}} The result should be 120
+----
+{{#c|"Sophos Style"}}
+ {{#b|➸ YAML}}
+ {{#b|➸ Test::A8N}}
+ {{#b|➸ Written by QA}}
+----
+ NAME: Admin changes their timezone
+ ID: admin_changes_tz
+ SUMMARY: Admins need to change their timezone.
+----
+ PRECONDITIONS:
+ - ensure user exists: admin
+ - ensure timezone is: America/Vancouver
+----
+ INSTRUCTIONS:
+ - login:
+ username: admin
+ password: testpass
+ - goto page: Account Settings
+ - verify current timezone is: America/Vancouver
+ - change timezone to: Australia/Brisbane
+ - verify current timezone is: Australia/Brisbane
+----
+ POSTCONDITIONS:
+ - ensure timezone is: America/Vancouver
+----
+{{#c|"Wikitest Style"}}
+ {{#b|➸ Wiki Tables}}
+ {{#b|➸ Keyword Driven}}
+ {{#b|➸ Based on Selenese}}
+ {{#b|➸ Written by Dev and QA}}
+----
+ {{#pre|| open | /login |}}
+ {{#pre|| title-is | Awesometown |}}
+ {{#pre|| text-like | //body | Welcome to Awesometown |}}
+----
+{{#c|Key Points}}
+----
+No contitionals
+or looping
+----
+Insulate Test Logic
+from {{#i|Test code}}
+----
+Risk Management
+----
+So we can
+☾ ✧ ☄
+sleep well
+----
+{{#c|Remember:}}
+There are no
+"Best Practices"
+----
+{{#c|Just:}}
+Better or Worse
+{{#i|for a given context}}
+----
+{{#c|5 Guidelines}}
+----
+❶ {{#i|Keep Up}}
+with development
+----
+❷ Make Tradeoffs
+{{#i|with intention}}
+----
+❸ Do the best
+{{#i|with what you have}}
+----
+Be resourceful
+with your team
+----
+Put people in a
+position they get
+excited about
+----
+❹ Balanced
+Breakfast
+----
+❺ Pay
+Attention
+----
+Periodical
+Reflection
+----
+Refactor
+your tests!
+----
+A8N costs $$$
+(So be pragmatic)
+----
+Questions‽
+----
+{{#c|Practical}}
+{{#c|Section}}
+----
+{{#c|OR:}} How our
+Breakfast
+has changed:
+----
+{{#c|Startup Time}}
+ 1 QA
+----
+Unit Tests
+Manual Testing
+Dogfood
+----
+{{#c|Dawn of Selenium}}
+ 1.5 QA
+----
+Selenium IDE
+ ☺ Easy to record
+ ☹ Hard to do anything else
+----
+Non-technical staff
+can write tests
+(but limiting!)
+----
+{{#c|Wikitest}}
+{{#c|Revolution}}
+----
+Built on Selenese
+ {{#b|➽ abstraction}}
+ {{#b|➽ less duplication}}
+ {{#b|➽ standardization}}
+----
+Keyword
+driven
+testing
+{{#s|FTW!}}
+----
+Express Tests
+in a Wiki Table
+----
+{{image src="wikitests.png" width="1234" height="392"}}
+----
+Suits the Team
+ {{#b|➺ Dogfood}}
+ {{#b|➺ Simple edit interface}}
+ {{#b|➺ Low barrier}}
+----
+Read the wiki table
+Execute the commands
+Produce results page
+----
+{{#c|Industrial}}
+Wikitest
+{{#c|Revolution}}
+----
+Interns++
+----
+Jump to 6,000
+test steps
+----
+A8N lags
+Development
+----
+But ...
+----
+No more
+regressions!
+----
+Overheard:
+{{#b|❝When was the last}}
+{{#b|bug we shipped?❞}}
+{{#s|(nobody knew)}}
+----
+{{#c|The Great}}
+{{#c|Depression}}
+{{#b|(QA layoffs)}}
+----
+Team loses QA
+
+{{#i|What to do?}}
+----
+{{#c|Answer:}}
+Change our
+practice
+----
+{{#c|Team agrees:}}
+Devs will write
+Sunny day A8N
+----
+Make the best
+out of what
+we have.
+----
+QA can focus
+on exceptions
+----
+Dev can write
+good A8N +
+Infrastructure
+----
+WIN-WIN-WIN
+----
+EOM
+----
+☃ Questions⁇ ☃
+----
+Links
+ ☑ {{#b|http://ingy.net}}
+ ♘ {{#b|http://cukes.info}}
+ ♨ {{#b|http://tinyurl.com/wikitests}}
+ ✈ {{#b|/sporx/}}
+ ♽ {{#b|/Test::A8N/}}
+
+</html:textarea>
+
+<deck flex="1" id="deck">
+ <vbox flex="1" onmousemove="Presentation.onMouseMoveOnCanvas(event);">
+ <toolbox id="canvasToolbar">
+ <toolbar>
+ <toolbarbutton oncommand="Presentation.home()" label="|&lt;&lt;" observes="canBack"/>
+ <toolbarbutton oncommand="Presentation.back()" label="&lt;" observes="canBack"/>
+ <toolbarbutton oncommand="Presentation.forward()" label="&gt;" observes="canForward"/>
+ <toolbarbutton oncommand="Presentation.end()" label="&gt;&gt;|" observes="canForward"/>
+ <toolbarseparator/>
+ <hbox align="center">
+ <textbox id="current_page" size="4" oninput="if (this.value) Presentation.showPage(parseInt(this.value)-1);"/>
+ <description value="/"/>
+ <description id="max_page"/>
+ </hbox>
+ <toolbarseparator/>
+ <vbox flex="2">
+ <spacer flex="1"/>
+ <scrollbar id="scroller" align="center" orient="horizontal" oncommand="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" onclick="Presentation.showPage(parseInt(event.target.getAttribute('curpos')));" onmousedown="Presentation.onScrollerDragStart();" onmousemove="Presentation.onScrollerDragMove();" onmouseup="Presentation.onScrollerDragDrop();"/>
+ <spacer flex="1"/>
+ </vbox>
+ <toolbarseparator/>
+ <spacer flex="1"/>
+ <toolbarseparator/>
+ <toolbarbutton id="toggleEva" label="Eva" type="checkbox" autoCheck="false" oncommand="Presentation.toggleEvaMode();"/>
+ <toolbarseparator/>
+ <toolbarbutton label="Edit" oncommand="Presentation.toggleEditMode();"/>
+ <toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
+ </toolbar>
+ </toolbox>
+ <vbox flex="1" id="canvas" onclick="Presentation.onPresentationClick(event);">
+ <spacer flex="1"/>
+ <hbox flex="1">
+ <spacer flex="1"/>
+ <vbox id="content"/>
+ <spacer flex="1"/>
+ </hbox>
+ <spacer flex="1"/>
+ </vbox>
+ </vbox>
+ <vbox flex="1" id="edit">
+ <toolbox>
+ <toolbar>
+ <toolbarbutton label="New Page" oncommand="Presentation.addPage()"/>
+ <spacer flex="1"/>
+ <toolbarseparator/>
+ <toolbarbutton label="View" oncommand="Presentation.toggleEditMode();"/>
+ <toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
+ </toolbar>
+ </toolbox>
+ <textbox id="textField" flex="1" multiline="true" oninput="Presentation.onEdit()"/>
+ <hbox collapsed="true">
+ <iframe id="dataLoader" onload="if (window.Presentation) Presentation.onDataLoad();"/>
+ </hbox>
+ </vbox>
+</deck>
+
+<broadcasterset>
+ <broadcaster id="canBack"/>
+ <broadcaster id="canForward"/>
+</broadcasterset>
+
+<commandset>
+ <command id="cmd_forward" oncommand="if (Presentation.isPresentationMode) Presentation.forward();"/>
+ <command id="cmd_back" oncommand="if (Presentation.isPresentationMode) Presentation.back();"/>
+ <command id="cmd_home" oncommand="if (Presentation.isPresentationMode) Presentation.home();"/>
+ <command id="cmd_end" oncommand="if (Presentation.isPresentationMode) Presentation.end();"/>
+</commandset>
+
+<keyset>
+ <key keycode="VK_ENTER" command="cmd_forward"/>
+ <key keycode="VK_RETURN" command="cmd_forward"/>
+ <key keycode="VK_PAGE_DOWN" command="cmd_forward"/>
+ <key keycode="VK_RIGHT" command="cmd_forward"/>
+ <key keycode="VK_DOWN" command="cmd_forward"/>
+ <!--key keycode="VK_BACK_SPACE" command="cmd_back"/-->
+ <key keycode="VK_UP" command="cmd_back"/>
+ <key keycode="VK_PAGE_UP" command="cmd_back"/>
+ <!--<key keycode="VK_BACK_UP" command="cmd_back"/>-->
+ <!--<key keycode="VK_BACK_LEFT" command="cmd_back"/>-->
+ <key keycode="VK_HOME" command="cmd_home"/>
+ <!--<key keycode="VK_END" command="cmd_end"/>-->
+ <key key="n" modifiers="accel" oncommand="Presentation.addPage();"/>
+ <key key="r" modifiers="accel" oncommand="window.location.reload();"/>
+ <key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/>
+ <key key="a" modifiers="accel" oncommand="Presentation.toggleEvaMode();"/>
+</keyset>
+
+
+<script src="lib/sporx.js" type="application/x-javascript" />
+
+</page>
+
+<!-- ***** BEGIN LICENSE BLOCK *****
+ - Version: MPL 1.1
+ -
+ - The contents of this file are subject to the Mozilla Public License Version
+ - 1.1 (the "License"); you may not use this file except in compliance with
+ - the License. You may obtain a copy of the License at
+ - http://www.mozilla.org/MPL/
+ -
+ - Software distributed under the License is distributed on an "AS IS" basis,
+ - WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ - for the specific language governing rights and limitations under the
+ - License.
+ -
+ - The Original Code is the Takahashi-Method-based Presentation Tool in XUL.
+ -
+ - The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ - Portions created by the Initial Developer are Copyright (C) 2005
+ - the Initial Developer. All Rights Reserved.
+ -
+ - Contributor(s): SHIMODA Hiroshi <piro@p.club.ne.jp>
+ -
+ - ***** END LICENSE BLOCK ***** -->
+
BIN  wikitests.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Please sign in to comment.
Something went wrong with that request. Please try again.