mirror of
https://github.com/Jermolene/TiddlyWiki5
synced 2024-06-26 15:23:15 +00:00
Merge branch 'master' into demo-alternate-store
This commit is contained in:
commit
9493084f95
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
|
@ -5,7 +5,7 @@ on:
|
|||
- master
|
||||
- tiddlywiki-com
|
||||
env:
|
||||
NODE_VERSION: "12"
|
||||
NODE_VERSION: "18"
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -14,7 +14,13 @@ jobs:
|
|||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: "${{ env.NODE_VERSION }}"
|
||||
- run: "./bin/test.sh"
|
||||
- run: "./bin/ci-test.sh"
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
build-prerelease:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.ref == 'refs/heads/master'
|
||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -5,4 +5,6 @@
|
|||
tmp/
|
||||
output/
|
||||
node_modules/
|
||||
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
|
|
16
bin/ci-test.sh
Executable file
16
bin/ci-test.sh
Executable file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/bash
|
||||
|
||||
# test TiddlyWiki5 for tiddlywiki.com
|
||||
|
||||
node ./tiddlywiki.js \
|
||||
./editions/test \
|
||||
--verbose \
|
||||
--version \
|
||||
--rendertiddler $:/core/save/all test.html text/plain \
|
||||
--test \
|
||||
|| exit 1
|
||||
|
||||
npm install playwright @playwright/test
|
||||
npx playwright install chromium firefox --with-deps
|
||||
|
||||
npx playwright test
|
|
@ -58,6 +58,7 @@ Last entry/entries in list
|
|||
exports.last = function(source,operator,options) {
|
||||
var count = $tw.utils.getInt(operator.operand,1),
|
||||
results = [];
|
||||
if(count === 0) return results;
|
||||
source(function(tiddler,title) {
|
||||
results.push(title);
|
||||
});
|
||||
|
|
|
@ -823,8 +823,8 @@ exports.hashString = function(str) {
|
|||
Base64 utility functions that work in either browser or Node.js
|
||||
*/
|
||||
if(typeof window !== 'undefined') {
|
||||
exports.btoa = window.btoa;
|
||||
exports.atob = window.atob;
|
||||
exports.btoa = function(binstr) { return window.btoa(binstr); }
|
||||
exports.atob = function(b64) { return window.atob(b64); }
|
||||
} else {
|
||||
exports.btoa = function(binstr) {
|
||||
return Buffer.from(binstr, 'binary').toString('base64');
|
||||
|
|
|
@ -28,6 +28,18 @@ Inherit from the base widget class
|
|||
*/
|
||||
ListWidget.prototype = new Widget();
|
||||
|
||||
ListWidget.prototype.initialise = function(parseTreeNode,options) {
|
||||
// Bail if parseTreeNode is undefined, meaning that the ListWidget constructor was called without any arguments so that it can be subclassed
|
||||
if(parseTreeNode === undefined) {
|
||||
return;
|
||||
}
|
||||
// First call parent constructor to set everything else up
|
||||
Widget.prototype.initialise.call(this,parseTreeNode,options);
|
||||
// Now look for <$list-template> and <$list-empty> widgets as immediate child widgets
|
||||
// This is safe to do during initialization because parse trees never change after creation
|
||||
this.findExplicitTemplates();
|
||||
}
|
||||
|
||||
/*
|
||||
Render this widget into the DOM
|
||||
*/
|
||||
|
@ -68,8 +80,6 @@ ListWidget.prototype.execute = function() {
|
|||
this.counterName = this.getAttribute("counter");
|
||||
this.storyViewName = this.getAttribute("storyview");
|
||||
this.historyTitle = this.getAttribute("history");
|
||||
// Look for <$list-template> and <$list-empty> widgets as immediate child widgets
|
||||
this.findExplicitTemplates();
|
||||
// Compose the list elements
|
||||
this.list = this.getTiddlerList();
|
||||
var members = [],
|
||||
|
@ -92,6 +102,7 @@ ListWidget.prototype.findExplicitTemplates = function() {
|
|||
var self = this;
|
||||
this.explicitListTemplate = null;
|
||||
this.explicitEmptyTemplate = null;
|
||||
this.hasTemplateInBody = false;
|
||||
var searchChildren = function(childNodes) {
|
||||
$tw.utils.each(childNodes,function(node) {
|
||||
if(node.type === "list-template") {
|
||||
|
@ -100,6 +111,8 @@ ListWidget.prototype.findExplicitTemplates = function() {
|
|||
self.explicitEmptyTemplate = node.children;
|
||||
} else if(node.type === "element" && node.tag === "p") {
|
||||
searchChildren(node.children);
|
||||
} else {
|
||||
self.hasTemplateInBody = true;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
@ -160,11 +173,11 @@ ListWidget.prototype.makeItemTemplate = function(title,index) {
|
|||
// Check for a <$list-item> widget
|
||||
if(this.explicitListTemplate) {
|
||||
templateTree = this.explicitListTemplate;
|
||||
} else if (!this.explicitEmptyTemplate) {
|
||||
} else if(this.hasTemplateInBody) {
|
||||
templateTree = this.parseTreeNode.children;
|
||||
}
|
||||
}
|
||||
if(!templateTree) {
|
||||
if(!templateTree || templateTree.length === 0) {
|
||||
// Default template is a link to the title
|
||||
templateTree = [{type: "element", tag: this.parseTreeNode.isBlock ? "div" : "span", children: [{type: "link", attributes: {to: {type: "string", value: title}}, children: [
|
||||
{type: "text", text: title}
|
||||
|
@ -414,4 +427,27 @@ ListItemWidget.prototype.refresh = function(changedTiddlers) {
|
|||
|
||||
exports.listitem = ListItemWidget;
|
||||
|
||||
/*
|
||||
Make <$list-template> and <$list-empty> widgets that do nothing
|
||||
*/
|
||||
var ListTemplateWidget = function(parseTreeNode,options) {
|
||||
// Main initialisation inherited from widget.js
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
ListTemplateWidget.prototype = new Widget();
|
||||
ListTemplateWidget.prototype.render = function() {}
|
||||
ListTemplateWidget.prototype.refresh = function() { return false; }
|
||||
|
||||
exports["list-template"] = ListTemplateWidget;
|
||||
|
||||
var ListEmptyWidget = function(parseTreeNode,options) {
|
||||
// Main initialisation inherited from widget.js
|
||||
this.initialise(parseTreeNode,options);
|
||||
};
|
||||
ListEmptyWidget.prototype = new Widget();
|
||||
ListEmptyWidget.prototype.render = function() {}
|
||||
ListEmptyWidget.prototype.refresh = function() { return false; }
|
||||
|
||||
exports["list-empty"] = ListEmptyWidget;
|
||||
|
||||
})();
|
||||
|
|
|
@ -89,7 +89,7 @@ $value={{{ [subfilter<get-field-value-tiddler-filter>get[text]] }}}/>
|
|||
</td>
|
||||
<td class="tc-edit-field-remove">
|
||||
<$button class="tc-btn-invisible" tooltip={{$:/language/EditTemplate/Field/Remove/Hint}} aria-label={{$:/language/EditTemplate/Field/Remove/Caption}}>
|
||||
<$action-deletefield $field=<<currentField>>/><$set name="currentTiddlerCSSescaped" value={{{ [<currentTiddler>escapecss[]] }}}><$action-sendmessage $message="tm-focus-selector" $param=<<current-tiddler-new-field-selector>>/></$set>
|
||||
<$action-deletefield $field=<<currentField>>/>
|
||||
{{$:/core/images/delete-button}}
|
||||
</$button>
|
||||
</td>
|
||||
|
|
|
@ -118,7 +118,7 @@ tags: $:/tags/Macro
|
|||
<$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item" >
|
||||
<li class=<<toc-item-class>>>
|
||||
<$link to={{{ [<currentTiddler>get[target]else<currentTiddler>] }}}>
|
||||
<$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>">
|
||||
<$list filter="[all[current]tagging[]$sort$limit[1]] -[subfilter<__exclude__>]" variable="ignore" emptyMessage="<$button class='tc-btn-invisible'>{{$:/core/images/blank}}</$button>">
|
||||
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-closed-icon>> />
|
||||
|
@ -145,7 +145,7 @@ tags: $:/tags/Macro
|
|||
<$qualify name="toc-state" title={{{ [[$:/state/toc]addsuffix<__path__>addsuffix[-]addsuffix<currentTiddler>] }}}>
|
||||
<$set name="toc-item-class" filter=<<__itemClassFilter__>> emptyValue="toc-item-selected" value="toc-item">
|
||||
<li class=<<toc-item-class>>>
|
||||
<$list filter="[all[current]tagging[]$sort$limit[1]]" variable="ignore" emptyMessage="""<$button class="tc-btn-invisible">{{$:/core/images/blank}}</$button><span class="toc-item-muted"><<toc-caption>></span>""">
|
||||
<$list filter="[all[current]tagging[]$sort$limit[1]] -[subfilter<__exclude__>]" variable="ignore" emptyMessage="""<$button class="tc-btn-invisible">{{$:/core/images/blank}}</$button><span class="toc-item-muted"><<toc-caption>></span>""">
|
||||
<$reveal type="nomatch" stateTitle=<<toc-state>> text="open">
|
||||
<$button setTitle=<<toc-state>> setTo="open" class="tc-btn-invisible tc-popup-keep">
|
||||
<$transclude tiddler=<<toc-closed-icon>> />
|
||||
|
|
25
editions/test/playwright.spec.js
Normal file
25
editions/test/playwright.spec.js
Normal file
|
@ -0,0 +1,25 @@
|
|||
const { test, expect } = require('@playwright/test');
|
||||
const {resolve} = require('path');
|
||||
|
||||
const indexPath = resolve(__dirname, 'output', 'test.html');
|
||||
const crossPlatformIndexPath = indexPath.replace(/^\/+/, '');
|
||||
|
||||
|
||||
test('get started link', async ({ page }) => {
|
||||
// The tests can take a while to run
|
||||
const timeout = 1000 * 30;
|
||||
test.setTimeout(timeout);
|
||||
|
||||
// Load the generated test TW html
|
||||
await page.goto(`file:///${crossPlatformIndexPath}`);
|
||||
|
||||
// Sanity check
|
||||
await expect(page.locator('.tc-site-title'), "Expected correct page title to verify the test page was loaded").toHaveText('TiddlyWiki5');
|
||||
|
||||
// Wait for jasmine results bar to appear
|
||||
await expect(page.locator('.jasmine-overall-result'), "Expected jasmine test results bar to be present").toBeVisible({timeout});
|
||||
|
||||
// Assert the tests have passed
|
||||
await expect(page.locator('.jasmine-overall-result.jasmine-failed'), "Expected jasmine tests to not have failed").not.toBeVisible();
|
||||
await expect(page.locator('.jasmine-overall-result.jasmine-passed'), "Expected jasmine tests to have passed").toBeVisible();
|
||||
});
|
|
@ -365,6 +365,7 @@ Tests the filtering mechanism.
|
|||
expect(wiki.filterTiddlers("[sort[title]first[8]]").join(",")).toBe("$:/ShadowPlugin,$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three");
|
||||
expect(wiki.filterTiddlers("[sort[title]first[x]]").join(",")).toBe("$:/ShadowPlugin");
|
||||
expect(wiki.filterTiddlers("[sort[title]last[]]").join(",")).toBe("TiddlerOne");
|
||||
expect(wiki.filterTiddlers("[sort[title]last[0]]").join(",")).toBe("");
|
||||
expect(wiki.filterTiddlers("[sort[title]last[2]]").join(",")).toBe("Tiddler Three,TiddlerOne");
|
||||
expect(wiki.filterTiddlers("[sort[title]last[8]]").join(",")).toBe("$:/TiddlerTwo,a fourth tiddler,filter regexp test,has filter,hasList,one,Tiddler Three,TiddlerOne");
|
||||
expect(wiki.filterTiddlers("[sort[title]last[x]]").join(",")).toBe("TiddlerOne");
|
||||
|
|
46
playwright.config.js
Normal file
46
playwright.config.js
Normal file
|
@ -0,0 +1,46 @@
|
|||
const { defineConfig, devices } = require('@playwright/test');
|
||||
|
||||
/**
|
||||
* @see https://playwright.dev/docs/test-configuration
|
||||
*/
|
||||
module.exports = defineConfig({
|
||||
testDir: './editions/test/',
|
||||
|
||||
// Allow parallel tests
|
||||
fullyParallel: true,
|
||||
|
||||
// Prevent accidentally committed "test.only" from wrecking havoc
|
||||
forbidOnly: !!process.env.CI,
|
||||
|
||||
// Do not retry tests on failure
|
||||
retries: 0,
|
||||
|
||||
// How many parallel workers
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
|
||||
// Reporter to use. See https://playwright.dev/docs/test-reporters
|
||||
reporter: 'html',
|
||||
|
||||
// Settings shared with all the tests
|
||||
use: {
|
||||
// Take a screenshot when the test fails
|
||||
screenshot: {
|
||||
mode: 'only-on-failure',
|
||||
fullPage: true
|
||||
}
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
}
|
||||
],
|
||||
});
|
||||
|
|
@ -56,6 +56,11 @@ name: tiddlywiki
|
|||
rendering-intent: auto;
|
||||
}
|
||||
|
||||
.tc-tiddler-frame .tc-tiddler-editor .tc-edit-texteditor,
|
||||
.tc-tiddler-frame .tc-tiddler-editor .tc-tiddler-preview-preview {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.cm-s-tiddlywiki.CodeMirror, .cm-s-tiddlywiki .CodeMirror-gutters { background-color: <<colour tiddler-editor-background>>; color: <<colour foreground>>; }
|
||||
.cm-s-tiddlywiki .CodeMirror-gutters {background: <<colour tiddler-editor-background>>; border-right: 1px solid <<colour tiddler-editor-border>>;}
|
||||
.cm-s-tiddlywiki .CodeMirror-linenumber {color: <<colour foreground>>;}
|
||||
|
|
Loading…
Reference in New Issue
Block a user