-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add hidden snapshot command for future implementation #120
Changes from all commits
64a42cb
e482c3a
37f8c5d
c5f7788
409e9d0
5de524c
1149bcb
f4b1428
ce050e0
1d468a5
baf61ae
1f7623b
5b085ba
cd99901
07d3e5a
b33b657
c096fd7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
import {flags} from '@oclif/command' | ||
import Constants from '../services/constants' | ||
import {StaticSnapshotOptions} from '../services/static-snapshot-options' | ||
import StaticSnapshotService from '../services/static-snapshot-service' | ||
import logger from '../utils/logger' | ||
import PercyCommand from './percy-command' | ||
|
||
export default class Snapshot extends PercyCommand { | ||
static description = 'Snapshot a directory containing a pre-built static website' | ||
static hidden = true | ||
|
||
static args = [{ | ||
name: 'snapshotDirectory', | ||
description: 'A path to the directory you would like to snapshot', | ||
required: true, | ||
}] | ||
|
||
static examples = [ | ||
'$ percy snapshot _site/', | ||
'$ percy snapshot _site/ --base-url "/blog"', | ||
'$ percy snapshot _site/ --ignore-files "\.(blog|docs)$"', | ||
] | ||
|
||
static flags = { | ||
'snapshot-files': flags.string({ | ||
char: 'c', | ||
description: 'Regular expression for matching the files to snapshot.', | ||
default: '\.(html|htm)$', | ||
}), | ||
'ignore-files': flags.string({ | ||
char: 'i', | ||
description: 'Regular expression for matching the files to ignore.', | ||
default: '', | ||
}), | ||
'base-url': flags.string({ | ||
char: 'b', | ||
description: 'If your static files will be hosted in a subdirectory, instead \n' + | ||
'of the webserver\'s root path, set that subdirectory with this flag.', | ||
default: '/', | ||
}), | ||
// from exec command. needed to start the agent service. | ||
'network-idle-timeout': flags.integer({ | ||
char: 't', | ||
default: Constants.NETWORK_IDLE_TIMEOUT, | ||
description: 'Asset discovery network idle timeout (in milliseconds)', | ||
}), | ||
'port': flags.integer({ | ||
char: 'p', | ||
default: Constants.PORT, | ||
description: 'Port', | ||
}), | ||
} | ||
|
||
async run() { | ||
await super.run() | ||
|
||
const {args, flags} = this.parse(Snapshot) | ||
|
||
const isWindows = process.platform === 'win32' | ||
|
||
const snapshotDirectory = args.snapshotDirectory as string | ||
const port = flags.port as number | ||
const staticServerPort = port + 1 | ||
const networkIdleTimeout = flags['network-idle-timeout'] as number | ||
const baseUrl = flags['base-url'] as string | ||
const ignoreFilesRegex = flags['ignore-files'] as string | ||
const snapshotFilesRegex = flags['snapshot-files'] as string | ||
|
||
// exit gracefully if percy will not run | ||
if (!this.percyWillRun()) { this.exit(0) } | ||
|
||
// check that base url starts with a slash and exit if it is missing | ||
if (baseUrl[0] !== '/') { | ||
logger.warn('The base-url flag must begin with a slash.') | ||
this.exit(1) | ||
} | ||
|
||
// start the agent service | ||
await this.agentService.start({port, networkIdleTimeout}) | ||
this.logStart() | ||
|
||
const options: StaticSnapshotOptions = { | ||
port: staticServerPort, | ||
snapshotDirectory, | ||
baseUrl, | ||
snapshotFilesRegex, | ||
ignoreFilesRegex, | ||
} | ||
|
||
const staticSnapshotService = new StaticSnapshotService(options) | ||
|
||
// start the snapshot service | ||
await staticSnapshotService.start() | ||
|
||
// take the snapshots | ||
await staticSnapshotService.snapshotAll() | ||
|
||
// stop the static snapshot and agent services | ||
await staticSnapshotService.stop() | ||
await this.agentService.stop() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
export interface StaticSnapshotOptions { | ||
snapshotDirectory: string, | ||
port: number, | ||
baseUrl: string, | ||
snapshotFilesRegex: string, | ||
ignoreFilesRegex?: string, | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import logger from '../utils/logger' | ||
import {StaticSnapshotOptions} from './static-snapshot-options' | ||
|
||
export default class StaticSnapshotService { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I read through this, I wonder if it would make sense to have the snapshot service extend the agent service? Or at least take care of the setup of the agent service in this constructor, so you don't have to do that in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
constructor(options: StaticSnapshotOptions) { | ||
// logger.info('calling constructor...') | ||
} | ||
|
||
async start() { | ||
// logger.info('starting static snapshot service...') | ||
} | ||
|
||
async snapshotAll() { | ||
// logger.info('taking snapshots of the static site...') | ||
} | ||
|
||
async stop() { | ||
// logger.info('stopping static snapshot service...') | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
import * as chai from 'chai' | ||
import {describe} from 'mocha' | ||
import * as sinon from 'sinon' | ||
import Snapshot from '../../src/commands/snapshot' | ||
import AgentService from '../../src/services/agent-service' | ||
import StaticSnapshotService from '../../src/services/static-snapshot-service' | ||
import {captureStdOut} from '../helpers/stdout' | ||
|
||
import {expect, test} from '@oclif/test' | ||
|
||
describe('snapshot', () => { | ||
describe('#run', () => { | ||
const sandbox = sinon.createSandbox() | ||
|
||
afterEach(() => { | ||
sandbox.restore() | ||
}) | ||
|
||
function AgentServiceStub(): AgentService { | ||
const agentService = AgentService.prototype as AgentService | ||
sandbox.stub(agentService, 'start') | ||
|
||
const start = new Snapshot([], '') as Snapshot | ||
sandbox.stub(start, 'agentService').returns(agentService) | ||
|
||
return agentService | ||
} | ||
|
||
function StaticSnapshotServiceStub(): StaticSnapshotService { | ||
const staticSnapshotService = StaticSnapshotService.prototype as StaticSnapshotService | ||
sandbox.stub(staticSnapshotService, 'snapshotAll') | ||
sandbox.stub(staticSnapshotService, 'start') | ||
|
||
return staticSnapshotService | ||
} | ||
|
||
it('starts the static snapshot service', async () => { | ||
const expectedAgentOptions = {networkIdleTimeout: 50, port: 5338} | ||
|
||
const agentServiceStub = AgentServiceStub() | ||
const staticSnapshotServiceStub = StaticSnapshotServiceStub() | ||
|
||
const stdout = await captureStdOut(async () => { | ||
await Snapshot.run(['./dummy-test-dir']) | ||
}) | ||
|
||
chai.expect(agentServiceStub.start).to.be.calledWith(expectedAgentOptions) | ||
chai.expect(staticSnapshotServiceStub.start).to.have.callCount(1) | ||
chai.expect(staticSnapshotServiceStub.snapshotAll).to.have.callCount(1) | ||
chai.expect(stdout).to.match(/\[percy\] percy has started./) | ||
}) | ||
|
||
xit('starts the snapshot service on the correct port') | ||
}) | ||
|
||
describe('snapshot command', () => { | ||
test | ||
.stub(process, 'env', {PERCY_TOKEN: ''}) | ||
.stderr() | ||
.command(['snapshot', './test_dir']) | ||
.exit(0) | ||
.do((output) => expect(output.stderr).to.contain( | ||
'Warning: Skipping visual tests. PERCY_TOKEN was not provided.', | ||
)) | ||
.it('warns about PERCY_TOKEN not being set and exits gracefully') | ||
|
||
test | ||
.env({PERCY_TOKEN: 'abc'}) | ||
.command(['snapshot']) | ||
.exit(2) | ||
.it('exits when the asset directory arg is missing') | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fab