Skip to content

Commit

Permalink
feat: slurps commands and events both bust node cache
Browse files Browse the repository at this point in the history
  • Loading branch information
AutoSponge committed Mar 31, 2020
1 parent 49b3008 commit e6b0350
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 117 deletions.
17 changes: 17 additions & 0 deletions lib/commands/_commands.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const test = require('ava');
const Scriptwriter = require('../scriptwriter');

test.serial('commands must bust cache on .clear', async (t) => {
const scriptwriter = new Scriptwriter();
t.is(scriptwriter.replServer, null);
let allReady = waitFor(scriptwriter, 'ready', ['client']);
await scriptwriter.init();
await allReady;
const replServer = scriptwriter.company.director;
const playbill = replServer.commands.playbill.action;
allReady = waitFor(scriptwriter, 'ready', ['client']);
replServer.commands.clear.action.call(replServer);
await allReady;
t.isNot(playbill, replServer.commands.playbill.action);
scriptwriter.company.director.close();
});
9 changes: 9 additions & 0 deletions lib/commands/clear-screen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
exports.name = 'clearScreen';
exports.command = {
help: 'Clears the screen',
action() {
const { scriptwriter, director } = this.context;
scriptwriter.log(scriptwriter.escapes.clearScreen);
director.displayPrompt();
},
};
26 changes: 26 additions & 0 deletions lib/commands/clear-screen.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const test = require('ava');
const clearScreen = require('./clear-screen');
const Scriptwriter = require('../scriptwriter');

test.serial('uses the correct interface', (t) => {
t.truthy(clearScreen.name);
t.truthy(clearScreen.command.help);
t.truthy(clearScreen.command.action);
});

test.serial('action', (t) => {
const scriptwriter = new Scriptwriter();
let displayPromptCalled = false;
const mockReplServer = {
context: {
scriptwriter,
director: {
displayPrompt() {
displayPromptCalled = true;
},
},
},
};
clearScreen.command.action.call(mockReplServer);
t.true(displayPromptCalled);
});
9 changes: 9 additions & 0 deletions lib/commands/clear-terminal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
exports.name = 'clearTerminal';
exports.command = {
help: 'Clears the screen and scroll buffer',
action() {
const { scriptwriter, director } = this.context;
scriptwriter.log(scriptwriter.escapes.clearTerminal);
director.displayPrompt();
},
};
26 changes: 26 additions & 0 deletions lib/commands/clear-terminal.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const test = require('ava');
const clearTerminal = require('./clear-terminal');
const Scriptwriter = require('../scriptwriter');

test.serial('uses the correct interface', (t) => {
t.truthy(clearTerminal.name);
t.truthy(clearTerminal.command.help);
t.truthy(clearTerminal.command.action);
});

test.serial('action', (t) => {
const scriptwriter = new Scriptwriter();
let displayPromptCalled = false;
const mockReplServer = {
context: {
scriptwriter,
director: {
displayPrompt() {
displayPromptCalled = true;
},
},
},
};
clearTerminal.command.action.call(mockReplServer);
t.true(displayPromptCalled);
});
65 changes: 65 additions & 0 deletions lib/commands/playbill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
const link = require('terminal-link');
const PLAYBILL = 'playbill';
const command = {
help: `List the scriptwriter's ${PLAYBILL}`,
action() {
const { scriptwriter, director } = this.context;
const credits = Object.keys(scriptwriter.company).sort();
const maxLength = Math.max(...credits.map((c) => c.length)) + 2;
scriptwriter.log(
credits
.map((c) =>
[
getLink(c),
' '.repeat(maxLength - c.length),
getDescription(c),
].join('')
)
.join('\n')
);
director.displayPrompt();
},
};
exports.name = PLAYBILL;
exports.command = command;

function getLink(name) {
const PLAYWRIGHT_API =
'https://github.com/microsoft/playwright/blob/v0.12.1/docs/api.md';
switch (name) {
case 'page':
case 'browser':
return link(name, `${PLAYWRIGHT_API}#class-${name}`);
case 'client':
return link(name, 'https://chromedevtools.github.io/devtools-protocol/');
case 'context':
return link(name, `${PLAYWRIGHT_API}#class-browser${name}`);
case 'director':
return link(name, 'https://nodejs.org/api/repl.html');
case 'playwright':
return link(name, PLAYWRIGHT_API);
case 'scriptwriter':
return link(name, 'https://github.com/AutoSponge/scriptwriter#readme');
default:
}
}

function getDescription(name) {
switch (name) {
case 'page':
return `Playwright's Page instance for the browser's context.`;
case 'browser':
return `Playwright's Browser instance.`;
case 'client':
return `Playwritght's CDPSession instance (Chrome only).`;
case 'context':
return `Playwright's BrowserContext instance for the browser.`;
case 'director':
return `Node's repl instance.`;
case 'playwright':
return `Playwright object.`;
case 'scriptwriter':
return `The instance object that controls the director.`;
default:
}
}
1 change: 1 addition & 0 deletions lib/events/client.enter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ module.exports = async function (scriptwriter) {
client.send('Runtime.enable'),
client.send('DOM.enable'),
]);
scriptwriter.emit('ready', 'client');
};
16 changes: 7 additions & 9 deletions lib/events/context.enter.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
module.exports = async function (scriptwriter) {
const { context } = scriptwriter.company;
try {
const page = await context.newPage();
scriptwriter.assign({ page });
if (context.newCDPSession) {
const client = await context.newCDPSession(page);
scriptwriter.assign({ client });
}
} catch (err) {
scriptwriter.log(err);
const page = await context.newPage();
await scriptwriter.assign({ page });
/* istanbul ignore next */
if (context.newCDPSession) {
const client = await context.newCDPSession(page);
await scriptwriter.assign({ client });
}
scriptwriter.emit('ready', 'context');
};
79 changes: 5 additions & 74 deletions lib/events/director.enter.js
Original file line number Diff line number Diff line change
@@ -1,78 +1,9 @@
const dlv = require('dlv');
const link = require('terminal-link');
const PLAYBILL = 'playbill';
const COMMAND_PLAYBILL = `.${PLAYBILL}`;

module.exports = function (scriptwriter) {
module.exports = async function (scriptwriter) {
const { director } = scriptwriter.company;
const { magenta } = scriptwriter.color;
scriptwriter.assign({ scriptwriter });
director.displayPrompt();
/* istanbul ignore if */
if (dlv(scriptwriter, `director.commands.${PLAYBILL}`)) return;
scriptwriter.log(magenta('.help for help. Tab twice for hints.'));
scriptwriter.completion = COMMAND_PLAYBILL;
director.defineCommand(PLAYBILL, {
help: `List the scriptwriter's ${PLAYBILL}`,
action() {
const credits = Object.keys(scriptwriter.company).sort();
const maxLength = Math.max(...credits.map((c) => c.length)) + 2;
scriptwriter.log(
credits
.map((c) =>
[
getLink(c),
' '.repeat(maxLength - c.length),
getDescription(c),
].join('')
)
.join('\n')
);
director.displayPrompt();
},
});

function getLink(name) {
const PLAYWRIGHT_API =
'https://github.com/microsoft/playwright/blob/v0.12.1/docs/api.md';
switch (name) {
case 'page':
case 'browser':
return link(name, `${PLAYWRIGHT_API}#class-${name}`);
case 'client':
return link(
name,
'https://chromedevtools.github.io/devtools-protocol/'
);
case 'context':
return link(name, `${PLAYWRIGHT_API}#class-browser${name}`);
case 'director':
return link(name, 'https://nodejs.org/api/repl.html');
case 'playwright':
return link(name, PLAYWRIGHT_API);
case 'scriptwriter':
return link(name, 'https://github.com/AutoSponge/scriptwriter#readme');
default:
}
}

function getDescription(name) {
switch (name) {
case 'page':
return `Playwright's Page instance for the browser's context.`;
case 'browser':
return `Playwright's Browser instance.`;
case 'client':
return `Playwritght's CDPSession instance (Chrome only).`;
case 'context':
return `Playwright's BrowserContext instance for the browser.`;
case 'director':
return `Node's repl instance.`;
case 'playwright':
return `Playwright object.`;
case 'scriptwriter':
return `The instance object that controls the director.`;
default:
}
if (!director.commands.playbill) {
scriptwriter.log(magenta('.help for help. Tab twice for hints.'));
}
await scriptwriter.defineCommands();
director.displayPrompt();
};
27 changes: 24 additions & 3 deletions lib/scriptwriter.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const ansiEscapes = require('ansi-escapes');
const prettier = require('prettier');

const EVENTS_PATH = resolve(__dirname, 'events');
const EVENTS_DIR = readdir(EVENTS_PATH);
const COMMANDS_PATH = resolve(__dirname, 'commands');
const EVENT_ASSIGN = 'assign';
const EVENT_ENTER = 'enter';

Expand Down Expand Up @@ -47,6 +47,9 @@ module.exports = class Scriptwriter extends EventEmitter {
*/
constructor(initialConfig = defaultConfig) {
super();
console.log();
const { device } = initialConfig;
device && assert(playwright.devices[device], `unknown device "${device}".`);
Object.entries(initialConfig).map(([k, v]) => config.set(k, v));
this.log = this.log.bind(this);
this.error = this.error.bind(this);
Expand Down Expand Up @@ -107,19 +110,35 @@ module.exports = class Scriptwriter extends EventEmitter {
assert.ok(assigned, `${assigned} not loaded.`);
this.completion = assignment;
if (!assigned.emit) return;
const listings = await EVENTS_DIR;
const listings = await readdir(EVENTS_PATH);
for (const list of listings) {
/* istanbul ignore if */
if (list.endsWith('.test.js')) continue;
const [role, event] = list.replace(/\.js$/, '').split('.');
if (assignment !== role) continue;
const file = resolve(EVENTS_PATH, list);
delete require.cache[file];
const handler = require(file);
const handle = handler.bind(null, this);
assigned[handler.once ? 'once' : 'on'](event, handle);
}
assigned.emit(EVENT_ENTER);
}
/**
* loads commands from folder
*/
async defineCommands() {
const listings = await readdir(COMMANDS_PATH);
for (const list of listings) {
/* istanbul ignore if */
if (list.endsWith('.test.js')) continue;
const file = resolve(COMMANDS_PATH, list);
delete require.cache[file];
const { command, name } = require(file);
this.completion = `.${name}`;
this.replServer.defineCommand(name, command);
}
}
/**
* Resets company and completions.
* Recycles the replServer.
Expand All @@ -143,9 +162,11 @@ module.exports = class Scriptwriter extends EventEmitter {
);
const director = this.replServer;
await this.assign({ director });
await this.assign({ scriptwriter: this });
const { browserType, launch } = this.config;
const browser = await playwright[browserType].launch(launch);
await this.assign({ playwright, browser });
await this.assign({ playwright });
await this.assign({ browser });
director.displayPrompt();
}
/**
Expand Down

0 comments on commit e6b0350

Please sign in to comment.