((resolve, reject) => {
+ const startTime = Date.now();
+ const interval = setInterval(() => {
+ if (condition()) {
+ clearInterval(interval);
+ clearTimeout(safetyTimeout);
+ resolve();
+ } else if (Date.now() - startTime >= timeout) {
+ clearInterval(interval);
+ clearTimeout(safetyTimeout);
+ resolve();
+ }
+ }, checkInterval);
+
+ const safetyTimeout = setTimeout(() => {
+ clearInterval(interval);
+ resolve();
+ }, timeout);
+ });
+};
+
export async function shouldShowUI() {
+ // cookie name is provided from split test package user config.
+ // Ensures it's loaded before calling the shouldShowUI function
+ await waitUntil(() => _config.cookieName === 'trustpilotABTest');
const promises = [
_config.globalCondition(userAgentInfo),
_config.uiCondition(userAgentInfo),
diff --git a/src/styles/ui.css b/src/styles/ui.css
index e4b3b62..840408c 100644
--- a/src/styles/ui.css
+++ b/src/styles/ui.css
@@ -11,6 +11,8 @@
transition: all .5s ease-out;
opacity: 1;
border-radius: 3px;
+ overflow: auto;
+ font-size: 12px;
}
.skift li.selected {
@@ -36,10 +38,6 @@
opacity: 0;
}
-.skift .tests {
- overflow-y: auto;
-}
-
.skift .variations {
background: #f4f7f9;
box-shadow: inset 0 0 1px 1px #dfe2e5;
@@ -95,11 +93,7 @@
}
.skift .icon {
- height: 16px;
- width: 16px;
display: inline-block;
- vertical-align: middle;
- margin: 0 4px;
cursor: pointer;
color: #0c59f2;
border: none;
diff --git a/src/ui.dev.ts b/src/ui.dev.ts
index e994407..31ccdfb 100644
--- a/src/ui.dev.ts
+++ b/src/ui.dev.ts
@@ -27,13 +27,12 @@ export const uiFactory = (
}
function renderLink(splitTest: SplitTest, variation: InternalVariation) {
- return renderButton(require('./images/link.svg'), () => {
- const input = document.createElement('input');
- input.value = splitTest.getVariationUrl(variation.name);
- document.body.appendChild(input);
- input.select();
+ return renderButton('currently active', () => {
+ const button = document.createElement('button');
+ button.value = splitTest.getVariationUrl(variation.name);
+ document.body.appendChild(button);
document.execCommand('copy');
- document.body.removeChild(input);
+ document.body.removeChild(button);
});
}
@@ -57,15 +56,10 @@ export const uiFactory = (
) {
const item = document.createElement('li');
item.textContent = variation.name;
- const open = renderButton(require('./images/open.svg'), () => {
+ const open = renderButton('change to this variant', () => {
setCurrentTestVariation(splitTest.name, variation.name);
});
-
- const link = renderLink(splitTest, variation);
-
item.appendChild(open);
- item.appendChild(link);
-
return item;
}
@@ -89,8 +83,8 @@ export const uiFactory = (
.map(
(key) => `
- ${key}
- ${data[key]}
+ ${key}
+ ${data[key]}
`,
)
@@ -121,19 +115,6 @@ export const uiFactory = (
variations.appendChild(list);
return [test, variations];
- } else {
- const canRun = await splitTest.shouldRun(getUserAgentInfo());
- const test = document.createElement('div');
- test.className = 'test';
- test.innerHTML = `
- Test ${splitTest.name} is not initialized
-
- Can run
- ${canRun}
-
- `;
-
- return [test];
}
}
@@ -166,12 +147,16 @@ export const uiFactory = (
.reduce((promise, futureElement) => {
return promise.then((elements) => {
return futureElement.then((element) => {
- elements.push(...element);
+ if (element && elements) {
+ elements.push(...element);
+ }
return elements;
});
});
}, Promise.resolve([]));
+ if (test) {
test.forEach((x) => testList.appendChild(x));
+ }
});
const button = document.createElement('button');
diff --git a/src/userAgentInfo.ts b/src/userAgentInfo.ts
index c7c7880..da1d0af 100644
--- a/src/userAgentInfo.ts
+++ b/src/userAgentInfo.ts
@@ -1,12 +1,15 @@
function getNameAndVersion() {
const ua = navigator.userAgent;
- let tem: RegExpMatchArray | null;
- let match: RegExpMatchArray = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
+ let tem: RegExpMatchArray | [] | null;
+ let match: RegExpMatchArray | [] =
+ ua.match(
+ /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i,
+ ) || [];
if (/trident/i.test(match[1])) {
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
return {
name: 'IE',
- version: (tem[1] || ''),
+ version: tem[1] || '',
};
}
if (match[1] === 'Chrome') {
@@ -18,7 +21,9 @@ function getNameAndVersion() {
};
}
}
- match = match[2] ? [match[1], match[2]] : [navigator.appName, navigator.appVersion, '-?'];
+ match = match[2]
+ ? [match[1], match[2]]
+ : [navigator.appName, navigator.appVersion, '-?'];
tem = ua.match(/version\/(\d+)/i);
if (tem !== null) {
match.splice(1, 1, tem[1]);
@@ -33,7 +38,14 @@ function isMobile() {
const ua = navigator.userAgent || navigator.vendor;
// Disable the rule for now and consider using RegExp constructor with a string.
// tslint:disable-next-line:max-line-length
- return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(ua) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(ua.substr(0, 4));
+ return (
+ /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(
+ ua,
+ ) ||
+ /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(
+ ua.substr(0, 4),
+ )
+ );
}
export interface UserAgentInfo {
diff --git a/tests/api.spec.ts b/tests/api.spec.ts
index 442df61..735db12 100644
--- a/tests/api.spec.ts
+++ b/tests/api.spec.ts
@@ -7,13 +7,12 @@ describe('Top-level api', () => {
expect(skift).toBeDefined();
});
- it('should be impossible to create an empty test', (done) => {
+ it('should be impossible to create an empty test', () => {
skift.create('Awesome test!').setup()
.then(() => expect('not').toBe('here'))
.catch((err) => {
expect(skift.getTest('Awesome test!')).toBeDefined();
expect(skift.getTest('Awesome test!') instanceof SplitTest).toBe(true);
- done();
});
});
@@ -25,7 +24,7 @@ describe('Top-level api', () => {
expect(test.getVariation('Variation A')).toBeDefined();
});
- it('should be possible to setup a test with two variations and retrieve it by name', async (done) => {
+ it('should be possible to setup a test with two variations and retrieve it by name', async () => {
const test = skift
.create('Another awesome test!')
.addVariation({ name: 'Variation C' })
@@ -34,7 +33,6 @@ describe('Top-level api', () => {
expect(await test.setup()).toBe(true);
expect(skift.getTest('Another awesome test!')).toBeDefined();
expect(test === skift.getTest('Another awesome test!')).toBeTruthy();
- done();
});
it('should be possible to show the UI', () => {
@@ -52,27 +50,25 @@ describe('Top-level api', () => {
});
describe('when setting a condition', () => {
- it('allows for a promise', async (done) => {
+ it('allows for a promise', async () => {
expect(await skift
.create('testing conditions')
.setCondition(() => Promise.resolve(true))
.addVariation({ name: 'A'})
.setup()).toBe(true);
- done();
});
- it('allows for a boolean', async (done) => {
+ it('allows for a boolean', async () => {
expect(await skift
.create('testing conditions')
.setCondition(() => true)
.addVariation({ name: 'A'})
.setup()).toBe(true);
- done();
});
});
describe('when checking for initialization', () => {
- it('resolves to true when setup is called, completes, and was successful', async (done) => {
+ it('resolves to true when setup is called, completes, and was successful', async () => {
const test = skift
.create('testing conditions')
.setCondition(() => true)
@@ -83,10 +79,9 @@ describe('Top-level api', () => {
await setupPromise;
expect(await initializedPromise).toBe(true);
- done();
});
- it('resolves to false when setup is called, completes, and was canceled', async (done) => {
+ it('resolves to false when setup is called, completes, and was canceled', async () => {
const test = skift
.create('testing conditions')
.setCondition(() => false)
@@ -97,10 +92,9 @@ describe('Top-level api', () => {
await setupPromise;
expect(await initializedPromise).toBe(false);
- done();
});
- it('resolves to false when setup is never called', async (done) => {
+ it('resolves to false when setup is never called', async () => {
const test = skift
.create('testing conditions')
.setCondition(() => false)
@@ -109,7 +103,6 @@ describe('Top-level api', () => {
const initializedPromise = test.isInitialized();
expect(await initializedPromise).toBe(false);
- done();
});
});
});