Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ jobs:
max_attempts: 5
shell: bash
command: npm run package-compass
# When lerna fails to publish, it leaves the repo in the dirty state
# that will mess up the following attempts
on_retry_command: git reset HEAD --hard
env:
HADRON_PRODUCT: mongodb-compass
HADRON_PRODUCT_NAME: MongoDB Compass
Expand Down Expand Up @@ -102,4 +105,4 @@ jobs:
if: ${{ cancelled() || failure() }}
with:
name: Spectron Debug Log ${{ runner.os }}
path: packages/compass-e2e-tests/.log/**/*.log
path: packages/compass-e2e-tests/.log/**/*
90 changes: 84 additions & 6 deletions packages/compass-e2e-tests/helpers/compass.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const Selectors = require('./selectors');
* @property {(selector: string, timeout?: number) => Promise<void>} clickVisible
* @property {(selector: string, value: any, timeout?: number) => Promise<void>} setValueVisible
* @property {() => Promise<void>} waitForConnectionScreen
* @property {() => Promise<void>} closeTourModal
* @property {() => Promise<void>} closePrivacySettingsModal
* @property {(timeout?: number) => Promise<void>} doConnect
* @property {(connectionString: string, timeout?: number) => Promise<void>} connectWithConnectionString
Expand Down Expand Up @@ -70,7 +71,12 @@ function getAtlasConnectionOptions() {
return { host, username, password, srvRecord: true };
}

// For the tmpdirs
let i = 0;
// For the screenshots
let j = 0;
// For the html
let k = 0;

/**
* @param {boolean} testPackagedApp Should compass start from the packaged binary or just from the source (defaults to source)
Expand Down Expand Up @@ -120,11 +126,7 @@ async function startCompass(

const shouldStoreAppLogs = process.env.ci || process.env.CI;

// Mimicking webdriver path with this for consistency
const nowFormatted = new Date()
.toISOString()
.replace(/:/g, '-')
.replace(/Z$/, '');
const nowFormatted = formattedDate();

if (shouldStoreAppLogs) {
const chromeDriverLogPath = path.join(
Expand Down Expand Up @@ -180,6 +182,11 @@ async function startCompass(
return app;
}

function formattedDate() {
// Mimicking webdriver path with this for consistency
return new Date().toISOString().replace(/:/g, '-').replace(/Z$/, '');
}

async function rebuildNativeModules(compassPath = COMPASS_PATH) {
const {
config: {
Expand Down Expand Up @@ -306,9 +313,39 @@ function addCommands(app) {
}
);

app.client.addCommand('closeTourModal', async function () {
// Wait a bit in any case if it exists or doesn't just so it has a chance to
// render if possible
await delay(1000);
if (await app.client.isExisting(Selectors.FeatureTourModal)) {
await app.client.waitUntil(
async () => {
return await app.client.isVisible(Selectors.FeatureTourModal);
},
1000,
'Expected feature tour modal to be visible',
50
);
// Wait a bit before clicking so that transition is through
await delay(100);
await app.client.clickVisible(Selectors.CloseFeatureTourModal);
await app.client.waitUntil(
async () => {
return !(await app.client.isExisting(Selectors.FeatureTourModal));
},
5000,
'Expected feature tour modal to disappear after closing it',
50
);
}
});

app.client.addCommand(
'closePrivacySettingsModal',
async function closePrivacySettingsModal() {
// Wait a bit in any case if it exists or doesn't just so it has a chance to
// render if possible
await delay(1000);
if (await app.client.isExisting(Selectors.PrivacySettingsModal)) {
await app.client.waitUntil(
async () => {
Expand Down Expand Up @@ -600,6 +637,45 @@ function addCommands(app) {
);
}

/**
* @param {ExtendedApplication} app
* @param {string} imgPathName
*/
async function capturePage(
app,
imgPathName = `screenshot-${formattedDate()}-${++j}.png`
) {
try {
const buffer = await app.browserWindow.capturePage();
await fs.mkdir(LOG_PATH, { recursive: true });
// @ts-expect-error buffer is Electron.NativeImage not a real buffer, but it
// can be used as a buffer when storing an image
await fs.writeFile(path.join(LOG_PATH, imgPathName), buffer);
return true;
} catch (_) {
return false;
}
}

/**
* @param {ExtendedApplication} app
* @param {string} htmlPathName
*/
async function savePage(
app,
htmlPathName = `page-${formattedDate()}-${++k}.html`
) {
try {
await app.webContents.savePage(
path.join(LOG_PATH, htmlPathName),
'HTMLComplete'
);
return true;
} catch {
return false;
}
}

module.exports = {
startCompass,
rebuildNativeModules,
Expand All @@ -608,7 +684,9 @@ module.exports = {
getCompassBinPath,
getAtlasConnectionOptions,
buildCompass,
capturePage,
savePage,
Selectors,
COMPASS_PATH,
LOG_PATH,
LOG_PATH
};
2 changes: 2 additions & 0 deletions packages/compass-e2e-tests/helpers/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ module.exports = {
ConnectSection: '[data-test-id="connect-section"]',
PrivacySettingsModal: '[data-test-id="privacy-settings-modal"]',
ClosePrivacySettingsButton: '[data-test-id="close-privacy-settings-button"]',
FeatureTourModal: '[data-test-id="feature-tour-modal"]',
CloseFeatureTourModal: '[data-test-id="close-tour-button"]',
ConnectButton: '[data-test-id="connect-button"]',
DatabasesTable: '[data-test-id="databases-table"]',
ConnectionStringInput: 'input[name="connectionString"]',
Expand Down
9 changes: 8 additions & 1 deletion packages/compass-e2e-tests/tests/smoke.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ const { expect } = require('chai');
const { createUnlockedKeychain } = require('../helpers/keychain');
const {
startCompass,
getAtlasConnectionOptions
getAtlasConnectionOptions,
capturePage,
savePage
} = require('../helpers/compass');

/**
Expand All @@ -20,12 +22,17 @@ describe('Compass', function () {
keychain.activate();
compass = await startCompass();
await compass.client.waitForConnectionScreen();
await compass.client.closeTourModal();
await compass.client.closePrivacySettingsModal();
});

after(async () => {
try {
if (compass) {
if (process.env.CI) {
await capturePage(compass);
await savePage(compass);
}
await compass.stop();
compass = null;
}
Expand Down
6 changes: 5 additions & 1 deletion packages/compass/src/app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,11 @@ var Application = View.extend({
var oldVersion = _.get(prefs, 'lastKnownVersion', '0.0.0');
var currentVersion = APP_VERSION;
var save = false;
if (semver.lt(oldVersion, currentVersion)) {
if (
semver.lt(oldVersion, currentVersion) ||
// So we can test the tour in any e2e environment, not only on prod
process.env.APP_ENV === 'spectron'
) {
prefs.showFeatureTour = oldVersion;
save = true;
}
Expand Down