Skip to content

Commit fe04be8

Browse files
committed
✅ testing instances
1 parent 2d025ff commit fe04be8

12 files changed

+276
-3
lines changed

client/objectEvent.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import client from './client';
2+
13
export default function objectEvent(node) {
24
for(const attribute in node.attributes) {
35
if(attribute.startsWith('on') && typeof(node.attributes[attribute]) === 'object') {
@@ -7,6 +9,7 @@ export default function objectEvent(node) {
79
for(const key in keys) {
810
target[key] = keys[key];
911
}
12+
client.update();
1013
}).bind(target);
1114
}
1215
}

tests/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
This folder contains tests for Nullstack using Jest and Puppeteer.
66

7-
## How to Install
7+
## How to install
88

99
```sh
1010
npm link

tests/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
"puppeteer": "^5.5.0"
1111
},
1212
"scripts": {
13-
"start": "npx webpack --config node_modules/nullstack/webpack.config.js --dir=./test --mode=development --watch",
14-
"build": "npx webpack --config node_modules/nullstack/webpack.config.js --dir=./test --mode=production",
13+
"start": "npx webpack --config node_modules/nullstack/webpack.config.js --dir=./tests --mode=development --watch",
14+
"build": "npx webpack --config node_modules/nullstack/webpack.config.js --dir=./tests --mode=production",
1515
"test": "jest"
1616
}
1717
}

tests/src/Application.njs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import Nullstack from 'nullstack';
22
import RenderableComponent from './RenderableComponent.njs';
3+
import StatefulComponent from './StatefulComponent.njs';
4+
import FullStackLifecycle from './FullStackLifecycle';
5+
import InstanceSelf from './InstanceSelf';
36

47
class Application extends Nullstack {
58

@@ -14,6 +17,9 @@ class Application extends Nullstack {
1417
<main>
1518
<h1> Nullstack Tests </h1>
1619
<RenderableComponent route="/renderable-component" />
20+
<StatefulComponent route="/stateful-component" />
21+
<FullStackLifecycle route="/full-stack-lifecycle" />
22+
<InstanceSelf route="/instance-self" />
1723
</main>
1824
)
1925
}

tests/src/FullStackLifecycle.njs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Nullstack from 'nullstack';
2+
3+
class FullStackLifecycle extends Nullstack {
4+
5+
prepared = false;
6+
initiated = false;
7+
hydrated = false;
8+
updated = false;
9+
10+
prepare() {
11+
this.prepared = true;
12+
}
13+
14+
async initiate() {
15+
this.initiated = true;
16+
}
17+
18+
hydrate() {
19+
this.hydrated = true;
20+
}
21+
22+
update() {
23+
if(!this.updated) {
24+
this.updated = true;
25+
}
26+
}
27+
28+
async terminate({params}) {
29+
params.terminated = true;
30+
}
31+
32+
render() {
33+
return (
34+
<div class="FullStackLifecycle">
35+
<div data-prepared={this.prepared} />
36+
<div data-initiated={this.initiated} />
37+
<div data-hydrated={this.hydrated} />
38+
<div data-updated={this.updated} />
39+
<a href="/"> Terminate </a>
40+
</div>
41+
)
42+
}
43+
44+
}
45+
46+
export default FullStackLifecycle;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
const puppeteer = require('puppeteer');
2+
3+
let browser;
4+
let page;
5+
6+
beforeAll(async () => {
7+
browser = await puppeteer.launch();
8+
page = await browser.newPage();
9+
await page.goto('http://localhost:5000/full-stack-lifecycle');
10+
});
11+
12+
describe('FullStackLifecycle', () => {
13+
14+
test('prepare should run', async () => {
15+
await page.waitForSelector('[data-prepared]');
16+
const element = await page.$('[data-prepared]');
17+
expect(element).toBeTruthy();
18+
});
19+
20+
test('initiate should run', async () => {
21+
await page.waitForSelector('[data-initiated]');
22+
const element = await page.$('[data-initiated]');
23+
expect(element).toBeTruthy();
24+
});
25+
26+
test('hydrate should run', async () => {
27+
await page.waitForSelector('[data-hydrated]');
28+
const element = await page.$('[data-hydrated]');
29+
expect(element).toBeTruthy();
30+
});
31+
32+
test('update should run', async () => {
33+
await page.waitForSelector('[data-updated]');
34+
const element = await page.$('[data-updated]');
35+
expect(element).toBeTruthy();
36+
});
37+
38+
test('terminate should run', async () => {
39+
await page.click('a[href="/"]');
40+
await page.waitForFunction(() => location.search == '?terminated=true');
41+
const element = await page.$('.FullStackLifecycle');
42+
expect(element).toBeFalsy();
43+
});
44+
45+
});
46+
47+
afterAll(async () => {
48+
browser.close();
49+
});

tests/src/InstanceSelf.njs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import Nullstack from 'nullstack';
2+
3+
class InstanceSelf extends Nullstack {
4+
5+
optimize = false;
6+
7+
render({self}) {
8+
return (
9+
<div class="InstanceSelf">
10+
<div data-initiated={self.initiated} />
11+
<div data-hydrated={self.hydrated} />
12+
<div data-prerendered={self.prerendered} />
13+
{self.hydrated &&
14+
<div data-class-name={self.element.className} />
15+
}
16+
</div>
17+
)
18+
}
19+
20+
}
21+
22+
export default InstanceSelf;

tests/src/InstanceSelf.test.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
const puppeteer = require('puppeteer');
2+
3+
let browser;
4+
let page;
5+
6+
beforeAll(async () => {
7+
browser = await puppeteer.launch();
8+
page = await browser.newPage();
9+
await page.goto('http://localhost:5000/instance-self');
10+
});
11+
12+
describe('InstanceSelf', () => {
13+
14+
test('self is aware that the component initiated', async () => {
15+
await page.waitForSelector('[data-initiated]');
16+
const element = await page.$('[data-initiated]');
17+
expect(element).toBeTruthy();
18+
});
19+
20+
test('self is aware that the component is hydrated', async () => {
21+
await page.waitForSelector('[data-hydrated]');
22+
const element = await page.$('[data-hydrated]');
23+
expect(element).toBeTruthy();
24+
});
25+
26+
test('self is aware that the component was prerendered', async () => {
27+
await page.waitForSelector('[data-prerendered]');
28+
const element = await page.$('[data-prerendered]');
29+
expect(element).toBeTruthy();
30+
});
31+
32+
test('self is aware of the component element', async () => {
33+
await page.waitForSelector('[data-class-name="InstanceSelf"]');
34+
const element = await page.$('[data-class-name="InstanceSelf"]');
35+
expect(element).toBeTruthy();
36+
});
37+
38+
});
39+
40+
afterAll(async () => {
41+
browser.close();
42+
});

tests/src/RenderableComponent.njs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class RenderableComponent extends Nullstack {
1515
)
1616
}
1717

18+
renderFalsy() {
19+
return false;
20+
}
21+
1822
transform() {
1923
this.condition = true;
2024
this.list = [1,2,3];
@@ -23,6 +27,7 @@ class RenderableComponent extends Nullstack {
2327
render() {
2428
return (
2529
<div class="RenderableComponent">
30+
<Falsy />
2631
<div> this is a normal tag </div>
2732
<label for="input"> label </label>
2833
<button disabled> disabled button </button>

tests/src/RenderableComponent.test.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ describe('RenderableComponent [condition=false]', () => {
7171
expect(element).toBeTruthy();
7272
});
7373

74+
test('headless components are allocated with a comment', async () => {
75+
const type = await page.$eval('.RenderableComponent', (element) => element.childNodes[0].nodeType);
76+
expect(type).toBe(8);
77+
});
78+
7479
});
7580

7681
describe('RenderableComponent [condition=true]', () => {

0 commit comments

Comments
 (0)