diff --git a/src/extension/background.js b/src/extension/background.js
index aa8ba713d..ac5c19d86 100644
--- a/src/extension/background.js
+++ b/src/extension/background.js
@@ -29,7 +29,6 @@ import {
getGitHubSettings,
setConfig,
getConfig,
- storeAuthToken,
updateProjectConfigs,
} from './utils.js';
@@ -117,8 +116,10 @@ async function guessIfFranklinSite({ id }) {
});
// listen for response message from tab
const listener = ({ isFranklinSite }) => {
- chrome.runtime.onMessage.removeListener(listener);
- resolve(isFranklinSite);
+ if (typeof isFranklinSite === 'boolean') {
+ chrome.runtime.onMessage.removeListener(listener);
+ resolve(isFranklinSite);
+ }
};
chrome.runtime.onMessage.addListener(listener);
});
@@ -330,6 +331,75 @@ function checkViewDocSource(id) {
});
}
+/**
+ * Sets the x-auth-token header for all requests to admin.hlx.page if project config
+ * has an auth token.
+ */
+async function updateAdminAuthHeaderRules() {
+ try {
+ // remove all rules first
+ await chrome.declarativeNetRequest.updateSessionRules({
+ removeRuleIds: (await chrome.declarativeNetRequest.getSessionRules())
+ .map((rule) => rule.id),
+ });
+ // find projects with auth tokens and add rules for each
+ let id = 1;
+ const projects = await getConfig('sync', 'hlxSidekickProjects') || [];
+ const addRules = [];
+ const projectConfigs = await Promise.all(projects.map((handle) => getConfig('sync', handle)));
+ projectConfigs.forEach(({ owner, repo, authToken }) => {
+ if (authToken) {
+ addRules.push({
+ id,
+ priority: 1,
+ action: {
+ type: 'modifyHeaders',
+ requestHeaders: [{
+ operation: 'set',
+ header: 'x-auth-token',
+ value: authToken,
+ }],
+ },
+ condition: {
+ regexFilter: `^https://admin.hlx.page/[a-z]+/${owner}/${repo}/.*`,
+ requestDomains: ['admin.hlx.page'],
+ requestMethods: ['get', 'post', 'delete'],
+ resourceTypes: ['xmlhttprequest'],
+ },
+ });
+ id += 1;
+ log.debug('added admin auth header rule for ', owner, repo);
+ }
+ });
+ if (addRules.length > 0) {
+ await chrome.declarativeNetRequest.updateSessionRules({
+ addRules,
+ });
+ log.debug(`setAdminAuthHeaderRule: ${addRules.length} rule(s) set`);
+ }
+ } catch (e) {
+ log.error(`updateAdminAuthHeaderRules: ${e.message}`);
+ }
+}
+
+async function storeAuthToken(owner, repo, token) {
+ // find config tab with owner/repo
+ const project = await getProject({ owner, repo });
+ if (project) {
+ if (token) {
+ project.authToken = token;
+ } else {
+ delete project.authToken;
+ }
+ await setProject(project);
+ log.debug(`updated auth token for ${owner}--${repo}`);
+ } else {
+ log.debug(`unable to update auth token for ${owner}--${repo}: no such config`);
+ }
+ // auth token changed, set/update admin auth header
+ updateAdminAuthHeaderRules();
+}
+
/**
* Adds the listeners for the extension.
*/
@@ -338,6 +408,7 @@ function checkViewDocSource(id) {
log.info(`sidekick extension installed (${reason})`);
await updateHelpContent();
await updateProjectConfigs();
+ await updateAdminAuthHeaderRules();
});
// register message listener
@@ -431,6 +502,22 @@ function checkViewDocSource(id) {
actions[actionFromTab](tab);
}
});
+
+ // listen for delete auth token calls from the content window
+ chrome.runtime.onMessage.addListener(async ({ deleteAuthToken }, { tab }) => {
+ // check if message contains project config and is sent from tab
+ if (tab && tab.id && typeof deleteAuthToken === 'object') {
+ const { owner, repo } = deleteAuthToken;
+ await storeAuthToken(owner, repo, '');
+ }
+ });
+
+ // for local debugging of header modification rules:
+ // 1. add "declarativeNetRequestFeedback" to permissions in manifest.json
+ // 2. uncomment the following 3 lines:
+ // chrome.declarativeNetRequest.onRuleMatchedDebug.addListener(({ request, rule }) => {
+ // console.log('rule matched', request.method, request.url, rule.ruleId);
+ // });
})();
// announce sidekick display state
diff --git a/src/extension/manifest.json b/src/extension/manifest.json
index 60311a8fc..55ea955b7 100644
--- a/src/extension/manifest.json
+++ b/src/extension/manifest.json
@@ -8,12 +8,14 @@
"options_page": "options.html",
"description": "__MSG_description__",
"permissions": [
+ "activeTab",
"contextMenus",
+ "declarativeNetRequest",
"scripting",
- "storage",
- "activeTab"
+ "storage"
],
"host_permissions": [
+ "https://www.hlx.live/tools/sidekick/*",
"http://localhost:3000/*",
"https://*/*"
],
diff --git a/src/extension/module.js b/src/extension/module.js
index 13cd67cde..9b044b436 100644
--- a/src/extension/module.js
+++ b/src/extension/module.js
@@ -888,15 +888,12 @@
* @param {object} config
* @returns {object}
*/
- function getAdminFetchOptions({ authToken }) {
+ function getAdminFetchOptions() {
const opts = {
cache: 'no-store',
credentials: 'include',
headers: {},
};
- if (authToken) {
- opts.headers['x-auth-token'] = authToken;
- }
return opts;
}
@@ -1791,6 +1788,18 @@
}
}
+ async function checkProfileStatus(sk, status) {
+ const url = getAdminUrl(sk.config, 'profile');
+ const opts = getAdminFetchOptions(sk.config);
+ return fetch(url, opts)
+ .then((res) => res.json())
+ .then((json) => {
+ console.log(json);
+ return json.status === status;
+ })
+ .catch(() => false);
+ }
+
/**
* Logs the user in.
* @private
@@ -1799,70 +1808,50 @@
*/
function login(sk, selectAccount) {
sk.showWait();
- const loginUrl = getAdminUrl(
- sk.config,
- 'login',
- sk.isProject() ? sk.location.pathname : '',
- );
- loginUrl.searchParams.set('loginRedirect', 'https://www.hlx.live/tools/sidekick/login-success');
+ const loginUrl = getAdminUrl(sk.config, 'login');
const extensionId = window.chrome?.runtime?.id;
- if (extensionId) {
+ const authHeaderEnabled = extensionId && !window.navigator.vendor.includes('Apple');
+ if (authHeaderEnabled) {
loginUrl.searchParams.set('extensionId', extensionId);
+ } else {
+ loginUrl.searchParams.set(
+ 'loginRedirect',
+ 'https://www.hlx.live/tools/sidekick/login-success',
+ );
}
if (selectAccount) {
loginUrl.searchParams.set('selectAccount', true);
}
- const profileUrl = new URL('https://admin.hlx.page/profile');
- if (sk.config.adminVersion) {
- profileUrl.searchParams.append('hlx-admin-version', sk.config.adminVersion);
- }
const loginWindow = window.open(loginUrl.toString());
- async function checkLoggedIn() {
- if ((await fetch(profileUrl.href, getAdminFetchOptions(sk.config))).ok) {
- window.setTimeout(() => {
- if (!loginWindow.closed) {
- loginWindow.close();
- }
- }, 500);
- delete sk.status.status;
- sk.addEventListener('statusfetched', () => sk.hideModal(), { once: true });
- sk.fetchStatus();
- fireEvent(sk, 'loggedin');
- return true;
- }
- return false;
- }
+ let attempts = 0;
- let seconds = 0;
- const loginCheck = window.setInterval(async () => {
- // give up after 2 minutes or window closed
- if (seconds >= 120 || loginWindow.closed) {
- window.clearInterval(loginCheck);
- loginWindow.close();
- // last check
- if (await checkLoggedIn()) {
+ async function checkLoggedIn() {
+ if (loginWindow.closed) {
+ attempts += 1;
+ // try 5 times after login window has been closed
+ if (await checkProfileStatus(sk, 200)) {
+ // logged in, stop checking
+ delete sk.status.status;
+ sk.addEventListener('statusfetched', () => sk.hideModal(), { once: true });
+ sk.fetchStatus();
+ fireEvent(sk, 'loggedin');
return;
}
-
- if (seconds >= 120) {
+ if (attempts >= 5) {
+ // give up after 5 attempts
sk.showModal({
message: i18n(sk, 'error_login_timeout'),
sticky: true,
level: 1,
});
- } else {
- sk.showModal({
- messsage: i18n(sk, 'error_login_aborted'),
- });
+ return;
}
}
-
- seconds += 1;
- if (await checkLoggedIn()) {
- window.clearInterval(loginCheck);
- }
- }, 1000);
+ // try again after 1s
+ window.setTimeout(checkLoggedIn, 1000);
+ }
+ window.setTimeout(checkLoggedIn, 1000);
}
/**
@@ -1871,29 +1860,47 @@
* @param {Sidekick} sk The sidekick
*/
function logout(sk) {
- const logoutUrl = new URL('https://admin.hlx.page/logout');
- if (sk.config.adminVersion) {
- logoutUrl.searchParams.append('hlx-admin-version', sk.config.adminVersion);
- }
-
- fetch(logoutUrl.href, {
- ...getAdminFetchOptions(sk.config),
- })
- .then(() => {
- delete sk.config.authToken;
- sk.status = {
- loggedOut: true,
- };
- })
- .then(() => fireEvent(sk, 'loggedout'))
- .then(() => sk.fetchStatus())
- .catch((e) => {
- console.error('logout failed', e);
- sk.showModal({
- message: i18n(sk, 'error_logout_error'),
- level: 0,
- });
- });
+ sk.showWait();
+ const logoutUrl = getAdminUrl(sk.config, 'logout');
+ const extensionId = window.chrome?.runtime?.id;
+ if (extensionId && !window.navigator.vendor.includes('Apple')) { // exclude safari
+ logoutUrl.searchParams.set('extensionId', extensionId);
+ } else {
+ logoutUrl.searchParams.set(
+ 'logoutRedirect',
+ 'https://www.hlx.live/tools/sidekick/logout-success',
+ );
+ }
+ const logoutWindow = window.open(logoutUrl.toString());
+
+ let attempts = 0;
+
+ async function checkLoggedOut() {
+ if (logoutWindow.closed) {
+ attempts += 1;
+ // try 5 times after login window has been closed
+ if (await checkProfileStatus(sk, 401)) {
+ delete sk.status.profile;
+ delete sk.config.authToken;
+ sk.addEventListener('statusfetched', () => sk.hideModal(), { once: true });
+ sk.fetchStatus();
+ fireEvent(sk, 'loggedout');
+ return;
+ }
+ if (attempts >= 5) {
+ // give up after 5 attempts
+ sk.showModal({
+ message: i18n(sk, 'error_logout_error'),
+ sticky: true,
+ level: 1,
+ });
+ return;
+ }
+ }
+ // try again after 1s
+ window.setTimeout(checkLoggedOut, 1000);
+ }
+ window.setTimeout(checkLoggedOut, 1000);
}
/**
@@ -2643,7 +2650,10 @@
throw new Error('error_status_invalid');
}
})
- .then((json) => Object.assign(this.status, json))
+ .then((json) => {
+ this.status = json;
+ return json;
+ })
.then((json) => fireEvent(this, 'statusfetched', json))
.catch(({ message }) => {
this.status.error = message;
diff --git a/src/extension/sidekick.js b/src/extension/sidekick.js
index 28c7d92c5..b2110b2a1 100644
--- a/src/extension/sidekick.js
+++ b/src/extension/sidekick.js
@@ -21,7 +21,6 @@ import {
setConfig,
setDisplay,
i18n,
- storeAuthToken,
} from './utils.js';
export default async function injectSidekick(config, display) {
@@ -105,11 +104,6 @@ export default async function injectSidekick(config, display) {
sk.addEventListener('hidden', () => {
setDisplay(false);
});
- sk.addEventListener('loggedout', async () => {
- // user clicked logout, delete the authToken from the config
- log.debug(`removing authToken from config ${owner}/${repo}`);
- await storeAuthToken(owner, repo, '');
- });
const helpOptOut = await getConfig('sync', 'hlxSidekickHelpOptOut');
if (!helpOptOut) {
// find next unacknowledged help topic with matching condition
diff --git a/src/extension/utils.js b/src/extension/utils.js
index 99f78f1e6..da36d7058 100644
--- a/src/extension/utils.js
+++ b/src/extension/utils.js
@@ -310,6 +310,7 @@ export async function getProject(project) {
export async function setProject(project, cb) {
const { owner, repo } = project;
const handle = `${owner}/${repo}`;
+ // update project config
await setConfig('sync', {
[handle]: project,
});
@@ -320,6 +321,7 @@ export async function setProject(project, cb) {
await setConfig('sync', { hlxSidekickProjects: projects });
}
log.info('updated project', project);
+
if (typeof cb === 'function') {
cb(project);
}
@@ -346,6 +348,9 @@ export async function deleteProject(handle, cb) {
const i = projects.indexOf(handle);
if (i >= 0) {
if (confirm(i18n('config_delete_confirm'))) {
+ // delete admin auth header rule
+ const [owner, repo] = handle.split('/');
+ chrome.runtime.sendMessage({ deleteAuthToken: { owner, repo } });
// delete the project entry
await removeConfig('sync', handle);
// remove project entry from index
@@ -380,22 +385,6 @@ export function toggleDisplay(cb) {
});
}
-export async function storeAuthToken(owner, repo, token) {
- // find config tab with owner/repo
- const project = await getProject({ owner, repo });
- if (project) {
- if (token) {
- project.authToken = token;
- } else {
- delete project.authToken;
- }
- await setProject(project);
- log.debug(`updated auth token for ${owner}--${repo}`);
- } else {
- log.warn(`unable to update auth token for ${owner}--${repo}: no such config`);
- }
-}
-
export async function updateProjectConfigs() {
const configs = await getConfig('sync', 'hlxSidekickConfigs');
const projects = await getConfig('sync', 'hlxSidekickProjects');
diff --git a/src/safari/helix-sidekick-extension.xcodeproj/project.pbxproj b/src/safari/helix-sidekick-extension.xcodeproj/project.pbxproj
index 3ab6143e2..e2bbdbf8a 100644
--- a/src/safari/helix-sidekick-extension.xcodeproj/project.pbxproj
+++ b/src/safari/helix-sidekick-extension.xcodeproj/project.pbxproj
@@ -719,7 +719,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
@@ -731,7 +731,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -750,7 +750,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "iOS (Extension)/Info.plist";
@@ -762,7 +762,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -785,7 +785,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "iOS (App)/Info.plist";
@@ -801,7 +801,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -824,7 +824,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "iOS (App)/Info.plist";
@@ -840,7 +840,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -862,7 +862,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/AEM Sidekick.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -875,7 +875,7 @@
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -894,7 +894,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "macOS (Extension)/AEM Sidekick.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -907,7 +907,7 @@
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -929,7 +929,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "macOS (App)/AEM Sidekick.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -943,7 +943,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
@@ -966,7 +966,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "macOS (App)/AEM Sidekick.entitlements";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = "6.12.5";
+ CURRENT_PROJECT_VERSION = "6.13.1";
DEVELOPMENT_TEAM = JQ525L2MZD;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
@@ -980,7 +980,7 @@
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.14;
- MARKETING_VERSION = "6.12.5";
+ MARKETING_VERSION = "6.13.1";
OTHER_LDFLAGS = (
"-framework",
SafariServices,
diff --git a/test/SidekickTest.js b/test/SidekickTest.js
index f0f67e77e..9918a39bf 100644
--- a/test/SidekickTest.js
+++ b/test/SidekickTest.js
@@ -85,7 +85,7 @@ import {
* @param {string} o.env=preview The environment (preview or live)
* @param {string} o.type=html The content type of the requested resource (html, xml or json)
* @param {string} o.fixture=generic.html The fixture file to use as test bed
- * @param {number} o.sleep=0 The number of milliseconds to wait after loading the sidekick
+ * @param {number} o.sleep=500 The number of milliseconds to wait after loading the sidekick
* @param {string} o.plugin A plugin to execute after loading the sidekick
* @param {number} o.pluginSleep=0 The number of milliseconds to wait after executing a plugin
* @param {boolean} acceptDialogs=false Defines whether dialogs will be accepted or dismissed
@@ -140,7 +140,7 @@ export class SidekickTest extends EventEmitter {
this.env = o.env || 'preview';
this.type = o.type || 'html';
this.fixture = o.fixture || 'generic.html';
- this.sleep = o.sleep ?? 0;
+ this.sleep = o.sleep ?? 500;
this.plugin = o.plugin;
this.pluginSleep = o.pluginSleep ?? 0;
this.acceptDialogs = o.acceptDialogs || false;
diff --git a/test/bulk-preview.test.js b/test/bulk-preview.test.js
index f4708ce50..298066756 100644
--- a/test/bulk-preview.test.js
+++ b/test/bulk-preview.test.js
@@ -63,6 +63,7 @@ describe('Test bulk preview plugin', () => {
const { plugins } = await new SidekickTest({
browser,
page,
+ sleep: 1000,
fixture: TESTS[0].fixture,
url: setup.getUrl('edit', 'admin'),
pre: (p) => p.evaluate(() => {
diff --git a/test/extension/chromeMock.js b/test/extension/chromeMock.js
index 3ae2ad2ac..5d899fff2 100644
--- a/test/extension/chromeMock.js
+++ b/test/extension/chromeMock.js
@@ -51,6 +51,7 @@ export default {
getManifest: async () => readFile({ path: '../../src/extension/manifest.json' }).then((mf) => JSON.parse(mf)),
getURL: (path) => `chrome-extension://${ID}${path}`,
lastError: null,
+ sendMessage: () => {},
},
storage: {
sync: new StorageMock({
@@ -73,4 +74,8 @@ export default {
test: 'test',
}),
},
+ declarativeNetRequest: {
+ getSessionRules: async () => ([]),
+ updateSessionRules: async () => undefined,
+ },
};
diff --git a/test/extension/utils.test.js b/test/extension/utils.test.js
index f6d07b003..92b22dd08 100644
--- a/test/extension/utils.test.js
+++ b/test/extension/utils.test.js
@@ -227,11 +227,11 @@ describe('Test extension utils', () => {
it('deleteProject', async () => {
const spy = sandbox.spy(window.chrome.storage.sync, 'set');
const deleted = await new Promise((resolve) => {
- utils.deleteProject('test/add-project', resolve);
+ utils.deleteProject('adobe/blog', resolve);
});
expect(deleted).to.be.true;
expect(spy.calledWith({
- hlxSidekickProjects: ['adobe/blog'],
+ hlxSidekickProjects: ['test/add-project'],
})).to.be.true;
});
diff --git a/test/login.test.js b/test/login.test.js
index 5adb3aa07..0d5a4bce4 100644
--- a/test/login.test.js
+++ b/test/login.test.js
@@ -13,7 +13,7 @@
import assert from 'assert';
import {
- DEBUG, IT_DEFAULT_TIMEOUT, Nock, sleep, TestBrowser,
+ IT_DEFAULT_TIMEOUT, Nock, TestBrowser,
} from './utils.js';
import { SidekickTest } from './SidekickTest.js';
@@ -47,55 +47,40 @@ describe('Test sidekick login', () => {
const test = new SidekickTest({
browser,
page,
- waitPopup: 2000,
+ pluginSleep: 2000,
plugin: 'user-login',
loadModule: true,
});
nock('https://admin.hlx.page')
.get('/status/adobe/blog/main/en/topics/bla?editUrl=auto')
- .times(2)
+ .twice()
.reply(function req() {
if (this.req.headers.cookie === 'auth_token=foobar') {
loggedIn = true;
- return [200, '{}', { 'content-type': 'application/json' }];
+ return [200, '{ "status": 200}', { 'content-type': 'application/json' }];
}
- return [401];
+ return [401, '{ "status": 401 }', { 'content-type': 'application/json' }];
})
- .get('/login/adobe/blog/main/en/topics/bla?loginRedirect=https%3A%2F%2Fwww.hlx.live%2Ftools%2Fsidekick%2Flogin-success')
- .times(DEBUG ? 2 : 1) // when dev-tools are enabled, browser makes 2 requests.
- .delay(1500) // delay so that 2 requests are made
- .reply(200, 'logged in!', {
+ .get('/login/adobe/blog/main?loginRedirect=https%3A%2F%2Fwww.hlx.live%2Ftools%2Fsidekick%2Flogin-success')
+ .reply(200, 'logged in', {
'set-cookie': 'auth_token=foobar; Path=/; HttpOnly; Secure; SameSite=None',
})
- .get('/profile')
- .times(2)
+ .get('/profile/adobe/blog/main')
.reply(function req() {
if (this.req.headers.cookie === 'auth_token=foobar') {
- return [200, '{}', { 'content-type': 'application/json' }];
+ return [200, '{ "status": 200 }', { 'content-type': 'application/json' }];
}
- return [401];
- });
+ return [401, '{ "status": 401 }', { 'content-type': 'application/json' }];
+ })
+ // in debug mode, the browser requests /favicon.ico
+ .get('/favicon.ico')
+ .optionally()
+ .reply(404);
await test.run();
- // wait until login window closes
- let loginClosed = false;
- await Promise.race([
- new Promise((resolve) => {
- page.browser().on('targetdestroyed', async (target) => {
- const targetUrl = target.url();
- if (targetUrl.startsWith('https://admin.hlx.page/login/adobe/blog/main/en/topics/bla')) {
- loginClosed = true;
- resolve();
- }
- });
- }),
- sleep(2000),
- ]);
-
assert.ok(loggedIn, 'Sidekick did not send auth cookie.');
- assert.ok(loginClosed, 'Sidekick did not close login window.');
}).timeout(IT_DEFAULT_TIMEOUT);
it('Opens login window and shows aborted modal', async () => {
@@ -103,26 +88,20 @@ describe('Test sidekick login', () => {
browser,
page,
plugin: 'user-login',
- pluginSleep: 2000,
+ pluginSleep: 7000, // sidekick tries 5 times before showing the login aborted modal
loadModule: true,
});
nock('https://admin.hlx.page')
.get('/status/adobe/blog/main/en/topics/bla?editUrl=auto')
- .reply(401)
- .get('/profile')
- .times(2)
- .reply(401)
- .get('/login/adobe/blog/main/en/topics/bla')
- .query({
- loginRedirect: 'https://www.hlx.live/tools/sidekick/login-success',
- })
- .reply(200, 'not logged in!');
+ .reply(401, '{ "status": 401 }', { 'content-type': 'application/json' })
+ .get('/login/adobe/blog/main?loginRedirect=https%3A%2F%2Fwww.hlx.live%2Ftools%2Fsidekick%2Flogin-success')
+ .reply(200, 'not logged in!')
+ .get('/profile/adobe/blog/main')
+ .times(5)
+ .reply(401, '{ "status": 401 }', { 'content-type': 'application/json' });
- const { popupTarget } = await test.run();
-
- // close login window
- await (await popupTarget.page()).close();
+ await test.run();
// wait for 'aborted' modal
try {
diff --git a/test/logout.test.js b/test/logout.test.js
index 7cc1e05c3..7fc1b02b3 100644
--- a/test/logout.test.js
+++ b/test/logout.test.js
@@ -45,14 +45,18 @@ describe('Test sidekick logout', () => {
it('Logout removes auth token from config', async () => {
nock.admin(new Setup('blog'));
nock('https://admin.hlx.page')
- .get('/logout')
- .reply(200, {});
- nock.admin(new Setup('blog'));
+ .get('/status/adobe/blog/main/en/topics/bla?editUrl=auto')
+ .reply(200, { status: 200 })
+ .get('/logout/adobe/blog/main?logoutRedirect=https%3A%2F%2Fwww.hlx.live%2Ftools%2Fsidekick%2Flogout-success')
+ .reply(200, 'logged out')
+ .get('/profile/adobe/blog/main')
+ .reply(401, '{ "status": 401 }', { 'content-type': 'application/json' });
+
const test = new SidekickTest({
browser,
page,
plugin: 'user-logout',
- sleep: 2000,
+ pluginSleep: 3000,
checkPage: async (p) => p.evaluate(() => window.hlx.sidekick.config),
});
test.sidekickConfig.authToken = 'foobar';