Skip to content
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

test(e2e): Add local npm registry for testing #134

Merged
merged 34 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
cde71b7
test(e2e): Add local npm registry for testing
louis-bompart Mar 31, 2021
822100c
Merge branch 'master' into CDX-212
louis-bompart Mar 31, 2021
b3c411e
stabilize
louis-bompart Apr 1, 2021
229676a
stabilize angular
louis-bompart Apr 1, 2021
79f037e
merge
louis-bompart Apr 1, 2021
7d9ac17
disable react tests
louis-bompart Apr 1, 2021
b6ce3a3
wrap process management
louis-bompart Apr 6, 2021
7b426d6
Merge branch 'master' into CDX-212
louis-bompart Apr 6, 2021
18bfb0e
all working
louis-bompart Apr 7, 2021
a2ecaf8
Merge remote-tracking branch 'origin/CDX-212' into CDX-212
louis-bompart Apr 7, 2021
7f35436
big timeout for slow CI
louis-bompart Apr 7, 2021
475089e
better server started detection condition
louis-bompart Apr 7, 2021
c1a5fe5
logging react toremove
louis-bompart Apr 7, 2021
b84f670
Revert "logging react toremove"
louis-bompart Apr 7, 2021
02a0994
logging react toremove
louis-bompart Apr 7, 2021
5d0e3ea
add alternative exit condition for react setup
louis-bompart Apr 7, 2021
51ccbb6
Revert "logging react toremove"
louis-bompart Apr 7, 2021
ac17bb3
rm timeout of angular
louis-bompart Apr 7, 2021
e277ba0
add openNewPage in react
louis-bompart Apr 7, 2021
5d43c60
revert unwanted changes in entrypoint
louis-bompart Apr 7, 2021
d4cc562
try no sudo
louis-bompart Apr 7, 2021
76c1f9d
sudo with no newline
louis-bompart Apr 7, 2021
824c004
Add better build detection for all test suites.
louis-bompart Apr 7, 2021
2b74d0b
check pid is a number
louis-bompart Apr 7, 2021
bcfb005
cleaning 1
louis-bompart Apr 7, 2021
dac402a
Merge branch 'master' into CDX-212
louis-bompart Apr 7, 2021
650c433
revert to non schematic
louis-bompart Apr 7, 2021
75615a4
leaner verdaccio config
louis-bompart Apr 7, 2021
7bbb0f6
refactor opennewpage
louis-bompart Apr 7, 2021
66f98c7
bubble up error
louis-bompart Apr 7, 2021
c9b8cdd
errorhandling
louis-bompart Apr 7, 2021
0cd9f07
debug
louis-bompart Apr 7, 2021
41377c9
error bubbling
louis-bompart Apr 7, 2021
eb54b50
muzzle yarn
louis-bompart Apr 8, 2021
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
19 changes: 1 addition & 18 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,9 @@ jobs:
- name: Build CLI
working-directory: ./packages/cli
run: tsc -b
- name: Set the template version
run: |
node scripts/store-next-test-version.js --variable=UI_TEMPLATE_VERSION --output=$GITHUB_ENV
- name: Bump template versions
run: |
echo "E2E tests should target template version ${{ env.UI_TEMPLATE_VERSION }}"
echo "//registry.npmjs.org/:_authToken=${{ env.NPM_TOKEN }}" > ~/.npmrc
louis-bompart marked this conversation as resolved.
Show resolved Hide resolved
npm run npm:bump:template -- -- ${{ env.UI_TEMPLATE_VERSION }}
npm run npm:publish:template
node scripts/wait-for-published-packages.js -v ${{ env.UI_TEMPLATE_VERSION }}
- uses: actions/upload-artifact@v2
if: failure()
with:
name: npm-logs
path: /home/runner/.npm/_logs/*debug.log
- name: End-to-end Tests
working-directory: ./packages/cli-e2e
run: |
echo "Running E2E tests with version ${{ env.UI_TEMPLATE_VERSION }}"
npm run test-e2e
run: npm run test-e2e
- uses: actions/upload-artifact@v2
with:
name: test-screenshots
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Coveo schematic for angular",
"scripts": {
"test": "npm run build && jasmine dist/**/*_spec.js",
"build": "tsc -p tsconfig.json",
"build": "tsc -p tsconfig.schematic.json",
Copy link
Collaborator Author

@louis-bompart louis-bompart Apr 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"prebuild": "node ./scripts/clean.js",
"postbuild": "node ./scripts/setup.js",
"prepublishOnly": "npm run build",
Expand Down
2 changes: 1 addition & 1 deletion packages/angular/src/search-token-server/rules/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export function startProxyServerFromRootApp(_options: CoveoSchema): Rule {
const packageJson = JSON.parse(packageJsonBuffer.toString());

packageJson.scripts['start'] =
'concurrently "npm run start-server" "ng serve"';
'concurrently --raw "npm run start-server" "ng serve"';
packageJson.scripts['start-server'] = 'node ./scripts/start-server.js';

tree.overwrite(
Expand Down
77 changes: 65 additions & 12 deletions packages/cli-e2e/__tests__/angular.specs.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
import retry from 'async-retry';

import type {ChildProcessWithoutNullStreams} from 'child_process';
import type {HTTPRequest, Browser, Page} from 'puppeteer';

import {setupUIProject, teardownUIProject} from '../utils/cli';
import {
answerPrompt,
getProjectPath,
isGenericYesNoPrompt,
setupUIProject,
} from '../utils/cli';
import {getNewBrowser} from '../utils/browser';
import {isSearchRequest} from '../utils/platform';
import {EOL} from 'os';
import stripAnsi from 'strip-ansi';
import {ProcessManager} from '../utils/processManager';

describe('ui', () => {
describe('create:angular', () => {
let browser: Browser;
const cliProcesses: ChildProcessWithoutNullStreams[] = [];
let processManager: ProcessManager;
// TODO: CDX-90: Assign a dynamic port for the search token server on all ui projects
const clientPort = '4200';
const projectName = 'angular-project';
Expand All @@ -19,16 +26,58 @@ describe('ui', () => {
let interceptedRequests: HTTPRequest[] = [];
let page: Page;

// TODO: Refactor.
louis-bompart marked this conversation as resolved.
Show resolved Hide resolved
const openNewPage = async () => {
const newPage = await browser.newPage();
if (page) {
await page.close();
}
return newPage;
};

beforeAll(async () => {
processManager = new ProcessManager();
browser = await getNewBrowser();
await setupUIProject('ui:create:angular', projectName, cliProcesses, {
flags: ['--defaults'],
timeout: 40e3,
const buildProcess = setupUIProject(
processManager,
'ui:create:angular',
projectName,
{
flags: ['--defaults'],
}
);

buildProcess.stdout.on('data', async (data) => {
if (isGenericYesNoPrompt(data.toString())) {
await answerPrompt(`y${EOL}`, buildProcess);
}
});

await new Promise<void>((resolve) => {
buildProcess.on('exit', async () => {
resolve();
});
});

const startServerProcess = processManager.spawn('npm', ['run', 'start'], {
cwd: getProjectPath(projectName),
});
}, 3e6);

await new Promise<void>((resolve) => {
startServerProcess.stdout.on('data', async (data) => {
if (
/Compiled successfully/.test(
stripAnsi(data.toString()).replace('/\n/g', '')
)
) {
resolve();
}
});
});
}, 420e3);

beforeEach(async () => {
page = await browser.newPage();
page = await openNewPage();

page.on('request', (request: HTTPRequest) => {
interceptedRequests.push(request);
Expand All @@ -42,7 +91,7 @@ describe('ui', () => {

afterAll(async () => {
await browser.close();
await teardownUIProject(cliProcesses);
await processManager.killAllProcesses();
}, 5e3);

it('should contain a search page section', async () => {
Expand All @@ -51,12 +100,16 @@ describe('ui', () => {
});

expect(await page.$('app-search-page')).not.toBeNull();
});
}, 300e3);

it('should retrieve the search token on the page load', async () => {
const tokenResponseListener = page.waitForResponse(tokenProxyEndpoint);

page.goto(searchPageEndpoint);
const tokenResponse = await page.waitForResponse(tokenProxyEndpoint);
expect(JSON.parse(await tokenResponse.text())).toMatchObject({

expect(
JSON.parse(await (await tokenResponseListener).text())
).toMatchObject({
token: expect.stringMatching(/^eyJhb.+/),
});
});
Expand Down
20 changes: 9 additions & 11 deletions packages/cli-e2e/__tests__/auth.specs.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
import {spawn} from 'child_process';
import retry from 'async-retry';

import type {Browser} from 'puppeteer';
import type {ChildProcessWithoutNullStreams} from 'child_process';

import {
answerPrompt,
CLI_EXEC_PATH,
isYesNoPrompt,
killCliProcess,
} from '../utils/cli';
import {answerPrompt, CLI_EXEC_PATH, isYesNoPrompt} from '../utils/cli';
import {captureScreenshots, connectToChromeBrowser} from '../utils/browser';
import {ProcessManager} from '../utils/processManager';

describe('auth', () => {
describe('login', () => {
let browser: Browser;
let cliProcess: ChildProcessWithoutNullStreams;
let processManager: ProcessManager;

beforeAll(async () => {
browser = await connectToChromeBrowser();
processManager = new ProcessManager();
});

afterEach(async () => {
await captureScreenshots(browser);
await killCliProcess(cliProcess);
await processManager.killAllProcesses();
}, 5e3);

it('should open the platform page', async () => {
// TODO CDX-98: Remove `-e=dev`.
cliProcess = spawn(CLI_EXEC_PATH, ['auth:login', '-e=dev']);
const cliProcess = processManager.spawn(CLI_EXEC_PATH, [
'auth:login',
'-e=dev',
]);
cliProcess.stderr.on('data', async (data) => {
if (isYesNoPrompt(data.toString())) {
await answerPrompt('n', cliProcess);
Expand Down
53 changes: 46 additions & 7 deletions packages/cli-e2e/__tests__/react.specs.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import retry from 'async-retry';

import type {ChildProcessWithoutNullStreams} from 'child_process';
import type {HTTPRequest, Browser, Page} from 'puppeteer';
import stripAnsi from 'strip-ansi';

import {setupUIProject, teardownUIProject} from '../utils/cli';
import {getNewBrowser} from '../utils/browser';
import {getProjectPath, setupUIProject} from '../utils/cli';
import {isSearchRequest} from '../utils/platform';
import {ProcessManager} from '../utils/processManager';

describe('ui', () => {
describe('create:react', () => {
let browser: Browser;
const cliProcesses: ChildProcessWithoutNullStreams[] = [];
let processManager: ProcessManager;
// TODO: CDX-90: Assign a dynamic port for the search token server on all ui projects
const clientPort = '3000';
const projectName = 'react-project';
Expand All @@ -21,10 +22,48 @@ describe('ui', () => {

beforeAll(async () => {
browser = await getNewBrowser();
await setupUIProject('ui:create:react', projectName, cliProcesses, {
timeout: 30e3,
processManager = new ProcessManager();
const buildProcess = setupUIProject(
processManager,
'ui:create:react',
projectName
);

await Promise.race([
new Promise<void>((resolve) => {
buildProcess.on('exit', async () => {
resolve();
});
}),
new Promise<void>((resolve) => {
buildProcess.stdout.on('data', (data) => {
if (
/Happy hacking!/.test(
stripAnsi(data.toString()).replace('/\n/g', '')
)
) {
resolve();
}
});
}),
]);

const startServerProcess = processManager.spawn('npm', ['run', 'start'], {
cwd: getProjectPath(projectName),
});
}, 3e6);

await new Promise<void>((resolve) => {
startServerProcess.stdout.on('data', async (data) => {
if (
/You can now view react-project in the browser/.test(
stripAnsi(data.toString()).replace('/\n/g', '')
)
) {
resolve();
}
});
});
}, 15 * 60e3);

beforeEach(async () => {
page = await browser.newPage();
Expand All @@ -41,7 +80,7 @@ describe('ui', () => {

afterAll(async () => {
await browser.close();
await teardownUIProject(cliProcesses);
await processManager.killAllProcesses();
}, 5e3);

it('should contain a search page section', async () => {
Expand Down
71 changes: 63 additions & 8 deletions packages/cli-e2e/__tests__/vue.specs.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
import retry from 'async-retry';

import type {ChildProcessWithoutNullStreams} from 'child_process';
import {mkdirSync, writeFileSync} from 'fs';
import {join} from 'path';
import type {HTTPRequest, Browser, Page} from 'puppeteer';

import {setupUIProject, teardownUIProject} from '../utils/cli';
import {
answerPrompt,
getProjectPath,
isGenericYesNoPrompt,
setupUIProject,
} from '../utils/cli';
import {captureScreenshots, getNewBrowser} from '../utils/browser';
import {isSearchRequest} from '../utils/platform';
import stripAnsi from 'strip-ansi';
import {EOL} from 'os';
import {ProcessManager} from '../utils/processManager';

describe('ui', () => {
describe('create:vue', () => {
let browser: Browser;
const cliProcesses: ChildProcessWithoutNullStreams[] = [];
// TODO: CDX-90: Assign a dynamic port for the search token server on all ui projects
const clientPort = '8080';
const projectName = 'vue-project';
const searchPageEndpoint = `http://localhost:${clientPort}`;
const tokenProxyEndpoint = `http://localhost:${clientPort}/token`;
let interceptedRequests: HTTPRequest[] = [];
let page: Page;

let processManager: ProcessManager;
const openNewPage = async () => {
const newPage = await browser.newPage();
if (page) {
Expand All @@ -28,9 +35,57 @@ describe('ui', () => {
};

beforeAll(async () => {
processManager = new ProcessManager();
browser = await getNewBrowser();
await setupUIProject('ui:create:vue', projectName, cliProcesses);
}, 240e3);
const projectPath = getProjectPath(projectName);
mkdirSync(projectPath, {recursive: true});
writeFileSync(
join(projectPath, '.yarnrc'),
'registry "http://verdaccio:4873"'
);
const buildProcess = setupUIProject(
processManager,
'ui:create:vue',
projectName
);

buildProcess.stdout.on('data', async (data) => {
if (
/Pick an action: \(Use arrow keys\)/.test(
stripAnsi(data.toString()).replace(/\n/g, '')
)
) {
await answerPrompt('\u001b[B', buildProcess);
return;
}
if (/❯ Merge/.test(stripAnsi(data.toString()))) {
louis-bompart marked this conversation as resolved.
Show resolved Hide resolved
await answerPrompt(EOL, buildProcess);
return;
}
if (isGenericYesNoPrompt(data.toString())) {
await answerPrompt(`y${EOL}`, buildProcess);
return;
}
});

await new Promise<void>((resolve) => {
buildProcess.on('exit', async () => {
resolve();
});
});

const startServerProcess = processManager.spawn('npm', ['run', 'start'], {
cwd: projectPath,
});

await new Promise<void>((resolve) => {
startServerProcess.stdout.on('data', async (data) => {
if (stripAnsi(data.toString()).indexOf('App running at:') !== -1) {
louis-bompart marked this conversation as resolved.
Show resolved Hide resolved
resolve();
}
});
});
}, 420e3);

beforeEach(async () => {
page = await openNewPage();
Expand All @@ -46,7 +101,7 @@ describe('ui', () => {

afterAll(async () => {
await browser.close();
await teardownUIProject(cliProcesses);
await processManager.killAllProcesses();
}, 5e3);

it('should contain a search page section', async () => {
Expand Down
Loading