mirror of
https://github.com/compiler-explorer/compiler-explorer.git
synced 2025-12-27 10:33:59 -05:00
Frontend testing (#3169)
This commit is contained in:
@@ -5,6 +5,7 @@ etc
|
||||
examples
|
||||
out
|
||||
views
|
||||
cypress
|
||||
|
||||
# Autogenerated files
|
||||
lib/asm-docs/generated/asm-docs-*.js
|
||||
|
||||
19
.github/workflows/test-frontend.yml
vendored
Normal file
19
.github/workflows/test-frontend.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Compiler Explorer Frontend Testing
|
||||
|
||||
on: [push]
|
||||
jobs:
|
||||
cypress-run:
|
||||
if: github.repository_owner == 'compiler-explorer'
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
- name: Clean
|
||||
run: make clean
|
||||
- name: Install prerequisites
|
||||
run: make prereqs
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v2
|
||||
with:
|
||||
start: npm run dev
|
||||
wait-on: 'http://localhost:10240'
|
||||
4
cypress.json
Normal file
4
cypress.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"baseUrl": "http://127.0.0.1:10240/",
|
||||
"downloadsFolder": "cypress/downloads"
|
||||
}
|
||||
15
cypress/integration/frontend-testing.js
Normal file
15
cypress/integration/frontend-testing.js
Normal file
@@ -0,0 +1,15 @@
|
||||
function runFrontendTest(name) {
|
||||
it(name, () => {
|
||||
cy.window().then((win) => {
|
||||
return win.compilerExplorerFrontendTesting.run(name);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
describe('Frontendtestresults', () => {
|
||||
before(() => {
|
||||
cy.visit('/');
|
||||
});
|
||||
|
||||
runFrontendTest('HelloWorld');
|
||||
});
|
||||
28
docs/internal/FrontendTesting.md
Normal file
28
docs/internal/FrontendTesting.md
Normal file
@@ -0,0 +1,28 @@
|
||||
# Frontend testing
|
||||
|
||||
We have a mixture of typescript in the main website's code (located in `static/tests`) and Cypress (located in `cypress/integration`) to test and report on the workings of that code.
|
||||
|
||||
But there's always the possibility to use Cypress code to do UI checks and testing.
|
||||
|
||||
## Recommended
|
||||
|
||||
The recommended way of testing is to use typescript to test the inner workings of the various interfaces that are available.
|
||||
|
||||
This has the advantage of having types and being able to verify your code is consistent with the rest of the website and probably going to run correctly - without having to startup the website and Cypress.
|
||||
|
||||
## Adding a test
|
||||
|
||||
Steps to add a test:
|
||||
|
||||
* Create a new file in `static/tests` (copy paste from `static/tests/hello-world.ts`)
|
||||
* Make sure to change the `description` as well as the test
|
||||
* Add the file to the imports of `static/tests/_all.js`
|
||||
* Add a `runFrontendTest()` call with the new test description to `cypress/integration/frontend-testing.js`
|
||||
|
||||
## Starting tests locally
|
||||
|
||||
You don't need to install an entire X server to actually run cypress (just xfvb).
|
||||
|
||||
You can find a complete list at https://docs.cypress.io/guides/getting-started/installing-cypress#System-requirements
|
||||
|
||||
If you have the prerequisites installed, you should be able to run `npx cypress run` - however, you will need to start the CE website seperately in another terminal before that.
|
||||
1270
package-lock.json
generated
1270
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -104,6 +104,7 @@
|
||||
"codecov": "^3.8.3",
|
||||
"css-loader": "^6.5.1",
|
||||
"css-minimizer-webpack-plugin": "^3.3.1",
|
||||
"cypress": "^9.2.0",
|
||||
"deep-equal-in-any-order": "^1.1.15",
|
||||
"eslint": "^8.5.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import { IFrontendTesting } from './tests/frontend-testing.interfaces';
|
||||
import { Options } from './options.interfaces';
|
||||
|
||||
type CompilerExplorerOptions = Record<string, unknown> & Options
|
||||
@@ -31,6 +32,7 @@ declare global {
|
||||
httpRoot: string | null;
|
||||
staticRoot: string | null;
|
||||
compilerExplorerOptions: CompilerExplorerOptions;
|
||||
compilerExplorerFrontendTesting: IFrontendTesting;
|
||||
ga: any;
|
||||
GoogleAnalyticsObject: any;
|
||||
}
|
||||
|
||||
@@ -52,6 +52,10 @@ var HistoryWidget = require('./history-widget').HistoryWidget;
|
||||
var History = require('./history');
|
||||
var presentation = require('./presentation');
|
||||
|
||||
if (!window.PRODUCTION) {
|
||||
require('./tests/_all');
|
||||
}
|
||||
|
||||
//css
|
||||
require('bootstrap/dist/css/bootstrap.min.css');
|
||||
require('golden-layout/src/css/goldenlayout-base.css');
|
||||
|
||||
2
static/tests/_all.js
Normal file
2
static/tests/_all.js
Normal file
@@ -0,0 +1,2 @@
|
||||
require('./frontend-testing');
|
||||
require('./hello-world');
|
||||
11
static/tests/frontend-testing.interfaces.ts
Normal file
11
static/tests/frontend-testing.interfaces.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
|
||||
export interface ITestable {
|
||||
readonly description: string;
|
||||
run(): Promise<void>;
|
||||
}
|
||||
|
||||
export interface IFrontendTesting {
|
||||
add(test: ITestable);
|
||||
getAllTestNames(): string[];
|
||||
run(testToRun: string): Promise<void>;
|
||||
}
|
||||
30
static/tests/frontend-testing.ts
Normal file
30
static/tests/frontend-testing.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { IFrontendTesting, ITestable } from './frontend-testing.interfaces';
|
||||
|
||||
class FrontendTesting implements IFrontendTesting {
|
||||
private testSuites: Array<ITestable> = [];
|
||||
|
||||
public add(test: ITestable) {
|
||||
this.testSuites.push(test);
|
||||
}
|
||||
|
||||
public getAllTestNames(): string[] {
|
||||
return this.testSuites.map((val) => val.description);
|
||||
}
|
||||
|
||||
private findTest(name: string) {
|
||||
for (const suite of this.testSuites) {
|
||||
if (suite.description === name) {
|
||||
return suite;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error(`Can't find test ${name}`);
|
||||
}
|
||||
|
||||
public async run(testToRun: string) {
|
||||
const testSuite = this.findTest(testToRun);
|
||||
await testSuite.run();
|
||||
}
|
||||
}
|
||||
|
||||
window.compilerExplorerFrontendTesting = new FrontendTesting();
|
||||
13
static/tests/hello-world.ts
Normal file
13
static/tests/hello-world.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { ITestable } from './frontend-testing.interfaces';
|
||||
import { assert } from 'chai';
|
||||
|
||||
class HelloWorldTests implements ITestable {
|
||||
public readonly description: string = 'HelloWorld';
|
||||
|
||||
public async run() {
|
||||
const person = true;
|
||||
assert.equal(person, true);
|
||||
}
|
||||
}
|
||||
|
||||
window.compilerExplorerFrontendTesting.add(new HelloWorldTests());
|
||||
@@ -30,7 +30,7 @@ import CssMinimizerPlugin from 'css-minimizer-webpack-plugin';
|
||||
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
|
||||
import MonacoEditorWebpackPlugin from 'monaco-editor-webpack-plugin';
|
||||
import TerserPlugin from 'terser-webpack-plugin';
|
||||
import {HotModuleReplacementPlugin, ProvidePlugin} from 'webpack';
|
||||
import {DefinePlugin, HotModuleReplacementPlugin, ProvidePlugin} from 'webpack';
|
||||
import {WebpackManifestPlugin} from 'webpack-manifest-plugin';
|
||||
|
||||
const __dirname = path.resolve(path.dirname(fileURLToPath(import.meta.url)));
|
||||
@@ -61,6 +61,9 @@ const plugins = [
|
||||
fileName: path.join(distPath, 'manifest.json'),
|
||||
publicPath: '',
|
||||
}),
|
||||
new DefinePlugin({
|
||||
'window.PRODUCTION': JSON.stringify(!isDev),
|
||||
}),
|
||||
];
|
||||
|
||||
if (isDev) {
|
||||
|
||||
Reference in New Issue
Block a user