@copperjs/copper
Version:
A lightweight chromium grid
182 lines • 9.64 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const sinon = require("sinon");
const path = require("path");
const fs = require("fs-extra");
const mkdirp = require("mkdirp");
const readDir = require("recursive-readdir");
const os = require("os");
const proxyquire = require("proxyquire");
const puppeteer = require("puppeteer-core");
const chai_1 = require("chai");
const errors_1 = require("../common/errors");
const config_1 = require("./config");
const fetchStub = sinon.stub();
const mkdirpStub = sinon.stub();
const chromeLaunch = sinon.stub();
const chromeKill = sinon.stub();
const { SessionManager } = proxyquire.noCallThru()('./sessionManager', {
'node-fetch': { default: fetchStub },
'chrome-launcher': { launch: chromeLaunch },
mkdirp: mkdirpStub,
});
describe('sessionManger', () => {
let sessionManager;
let tmpdir;
beforeEach(async () => {
sessionManager = new SessionManager();
tmpdir = path.join(os.tmpdir(), 'unittests');
await mkdirp(tmpdir);
fetchStub.resolves({ json: () => ({ webSocketDebuggerUrl: 'webSocketDebuggerUrl' }) });
mkdirpStub.resolves();
chromeLaunch.resolves({ port: 1, pid: 2, kill: chromeKill });
config_1.copperConfig.value.enableW3CProtocol = false;
});
afterEach(async () => {
sinon.restore();
fetchStub.reset();
mkdirpStub.reset();
chromeLaunch.reset();
chromeKill.reset();
config_1.copperConfig.reset();
await fs.remove(tmpdir);
});
describe('parse configuration', () => {
it("should parse chromeOptions from desiredCapabilities['goog:chromeOptions']", () => {
const opts = {};
chai_1.expect(sessionManager.getChromeOptions({ 'goog:chromeOptions': opts })).to.equal(opts);
});
it('should parse chromeOptions from desiredCapabilities.chromeOptions', () => {
const opts = {};
chai_1.expect(sessionManager.getChromeOptions({ chromeOptions: opts })).to.equal(opts);
});
it('should parse capabilities from desiredCapabilities.capabilities.firstMatch', () => {
const caps = {};
chai_1.expect(sessionManager.parseSessionRequest({ capabilities: { firstMatch: [caps] } }).capabilities).to.equal(caps);
});
it('should parse capabilities from desiredCapabilities.desiredCapabilities', () => {
const caps = {};
chai_1.expect(sessionManager.parseSessionRequest({ desiredCapabilities: caps }).capabilities).to.equal(caps);
});
it('should have default desiredCapabilities', () => {
chai_1.expect(sessionManager.parseSessionRequest().capabilities).to.eql({ browserName: 'chrome' });
});
});
describe('webdriver specific args', () => {
it('should handle chrome profile', async () => {
sinon.stub(os, 'tmpdir').returns(tmpdir);
await sessionManager.handleChromeProfile();
chai_1.expect(mkdirpStub).to.have.been.calledWith(`${tmpdir}/puppeteer_dev_chrome_profile-`);
});
it('should unzip an extension and save it locally', async () => {
const EMPTY_ZIP = 'UEsDBBQACAAIAIBT5FIAAAAAAAAAAAEAAAANACAAZW1wdHlmaWxlLnR4dFVUDQAHAGPhYLRm4WCyZuFgdXgLAAEE9QEAAAQUAAAAMwQAUEsHCLfv3IMDAAAAAQAAAFBLAQIUAxQACAAIAIBT5FK379yDAwAAAAEAAAANACAAAAAAAAAAAACkgQAAAABlbXB0eWZpbGUudHh0VVQNAAcAY+FgtGbhYLJm4WB1eAsAAQT1AQAABBQAAABQSwUGAAAAAAEAAQBbAAAAXgAAAAAA';
await sessionManager.saveExtensionLocally(EMPTY_ZIP, tmpdir);
const files = await readDir(tmpdir);
chai_1.expect(files).to.have.lengthOf(1);
chai_1.expect(files[0]).to.contain('emptyfile.txt');
});
it('should cache extensions that are already uploaded', async () => {
const EMPTY_ZIP = 'UEsFBgAAAAAAAAAAAAAAAAAAAAAAAA==';
const upload1 = await sessionManager.saveExtensionLocally(EMPTY_ZIP, tmpdir);
const upload2 = await sessionManager.saveExtensionLocally(EMPTY_ZIP, tmpdir);
chai_1.expect(upload1).to.equal(upload2);
});
it('should throw on invalid zip files', async () => {
const INVALID_ZIP = 'abcd';
await chai_1.expect(sessionManager.saveExtensionLocally(INVALID_ZIP, '/path/does/not/exist')).to.be
.rejected;
});
it('should handle multiple extensions', async () => {
const EMPTY_ZIP = 'UEsFBgAAAAAAAAAAAAAAAAAAAAAAAA==';
sinon.stub(os, 'tmpdir').returns(tmpdir);
await sessionManager.handleExtensions({ chromeOptions: { extensions: [EMPTY_ZIP] } }, 'extensions');
chai_1.expect(mkdirpStub).to.have.been.calledWith(`${tmpdir}/extensions`);
});
it('should ignore a session with no extensions passed', async () => {
sinon.stub(os, 'tmpdir').returns(tmpdir);
await sessionManager.handleExtensions({}, 'extensions');
chai_1.expect(mkdirpStub).to.not.have.been.called;
});
});
describe('createSession', () => {
it('should create a session', async () => {
const session = await sessionManager.createSession();
chai_1.expect(session).to.shallowDeepEqual({ pid: 2, port: 1 });
chai_1.expect(chromeLaunch).to.have.been.calledWith({});
});
it('should accept args from chromeOptions', async () => {
await sessionManager.createSession({
chromeOptions: { chromeFlags: ['--foo'] },
});
chai_1.expect(chromeLaunch).to.have.been.calledWith({ chromeFlags: ['--foo'] });
});
it('should accept args from desiredCapabilities', async () => {
await sessionManager.createSession({
desiredCapabilities: { chromeOptions: { args: ['--foo'] }, browserName: 'chrome' },
});
chai_1.expect(chromeLaunch).to.have.been.calledWith({ chromeFlags: ['--foo'], ignoreDefaultFlags: true });
});
it('should throw error when failed to create a browser', async () => {
chromeLaunch.rejects();
await chai_1.expect(sessionManager.createSession()).to.be.rejectedWith(errors_1.CreateSessionError);
});
it('should create a puppeteer instance when enableW3CProtocol is enabled', async () => {
config_1.copperConfig.value.enableW3CProtocol = true;
const stub = sinon.stub(puppeteer, 'connect').resolves({ pages: () => Promise.resolve([]) });
const session = await sessionManager.createSession();
chai_1.expect(session).to.shallowDeepEqual({ pid: 2, port: 1 });
chai_1.expect(stub).to.have.been.calledWith({ browserWSEndpoint: 'webSocketDebuggerUrl' });
});
});
describe('removeSession', () => {
it('should remove a session', async () => {
const session = await sessionManager.createSession();
await sessionManager.removeSession(session.id);
chai_1.expect(chromeKill).to.have.been.called;
});
it('should catch when failed to remove a session', async () => {
chromeKill.rejects();
const session = await sessionManager.createSession();
await chai_1.expect(sessionManager.removeSession(session.id)).not.to.be.rejected;
});
it('should disconnect puppeteer instance when exists', async () => {
config_1.copperConfig.value.enableW3CProtocol = true;
const stub = sinon.stub().resolves();
sinon.stub(puppeteer, 'connect').resolves({ pages: () => Promise.resolve([]), disconnect: stub });
const session = await sessionManager.createSession();
await sessionManager.removeSession(session.id);
chai_1.expect(stub).to.have.been.called;
});
});
it('should return session websocket url', async () => {
const session = await sessionManager.createSession();
chai_1.expect(sessionManager.getWebSocketUrl(session.id)).to.equal('webSocketDebuggerUrl');
});
it('should return session puppeteer instance', async () => {
config_1.copperConfig.value.enableW3CProtocol = true;
const pages = [{}];
const puppeteerInstance = { pages: () => Promise.resolve(pages) };
sinon.stub(puppeteer, 'connect').resolves(puppeteerInstance);
const session = await sessionManager.createSession();
chai_1.expect(sessionManager.getPuppeteer(session.id)).to.eql({ browser: puppeteerInstance, page: pages[0] });
});
it('should not have a puppeteer instance when enableW3CProtocol is disabled', async () => {
config_1.copperConfig.value.enableW3CProtocol = false;
const session = await sessionManager.createSession();
chai_1.expect(sessionManager.getPuppeteer(session.id)).to.be.undefined;
});
it('should get a session by id', async () => {
const session = await sessionManager.createSession();
chai_1.expect(sessionManager.getSession(session.id)).to.eql(session);
});
it('should throw when no matching session', () => {
chai_1.expect(() => sessionManager.getSession('foo')).to.throw(errors_1.SessionNotFound);
});
it('should list all sessions', async () => {
const session = await sessionManager.createSession();
const sessions = await sessionManager.listSessions();
chai_1.expect(sessions).to.have.lengthOf(1);
chai_1.expect(sessions[0]).to.shallowDeepEqual(session);
});
});
//# sourceMappingURL=sessionManager.test.js.map