Skip to content

Commit

Permalink
Pewpew "latest" version view into scripting. (#205)
Browse files Browse the repository at this point in the history
* Added eslint key-spacing rule (#204)

* Adding toaster, dynamically checking pewpewVersion (#201)

* adding files to dynamically show latest
pewpew version on Toaster

* cleaning up code for lintter to pass

* refactoring code to use tags in S3

* removing files from tsconfig

* fixing lint rules

* fixing spacing as local linter didnt catch those but the build did

* missed one space

* adding tests, cleaning up files

* removing trailing spaces failing on build

* adding DS_Store - make specific file to gitignore

* updating storybook to show pewpew latest version output

---------

Co-authored-by: Bryan <[email protected]>
  • Loading branch information
tkmcmaster and bryan-e-lopez authored Mar 19, 2024
1 parent f68ad95 commit 77a4464
Show file tree
Hide file tree
Showing 18 changed files with 204 additions and 22 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"space-infix-ops":"warn",
"space-before-blocks": "warn",
"keyword-spacing": "warn",
"key-spacing": 1,
"strict": 1,
"comma-dangle": 1,
"triple-equals": 0,
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@ testmerge.json
.env.development.local*
.env.test.local*
.env.production.local*

.DS_Store
2 changes: 1 addition & 1 deletion agent/test/pewpewtest.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ describe("PewPewTest", () => {
endTime: now + 2,
resultsFilename: ["test2"],
status: TestStatus.Failed,
version:"version3",
version: "version3",
userId: "user3"
};

Expand Down
5 changes: 5 additions & 0 deletions controller/components/PewPewVersions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Danger } from "../Alert";
import Div from "../Div";
import React from "react";
import Toaster from "../Toaster";
import styled from "styled-components";

const VersionDiv = styled(Div)`
Expand All @@ -24,6 +25,7 @@ const VersionDivSelect = styled(Div)`
export interface VersionInitalProps {
pewpewVersion: string;
pewpewVersions: string[];
latestPewPewVersion: string;
loading: boolean;
error: boolean;
}
Expand All @@ -38,12 +40,14 @@ export const PewPewVersions = ({
name,
pewpewVersion,
onChange,
latestPewPewVersion: latestPewPewTag,
pewpewVersions = [],
loading,
error
}: VersionProps) => {
// console.log("PewPewVersions state", { pewpewVersions, loading, error });
let optionItems: JSX.Element[] | undefined;
const toasterMessage: string = "IMPORTANT: Please configure your YAML properly!!! The latest version of Pewpew is set to: " + latestPewPewTag;
if (pewpewVersions && pewpewVersions.length > 0) {
optionItems = pewpewVersions.map((version: string) => (<option value={version} key={version}>{version}</option>));
}
Expand All @@ -53,6 +57,7 @@ export const PewPewVersions = ({
{loading && <VersionDivSelect>Loading...</VersionDivSelect>}
{!loading && !error && <VersionDivSelect><select name={name} value={pewpewVersion} onChange={onChange}>{optionItems} </select></VersionDivSelect>}
{error && <VersionDivSelect><Danger>Could not load the current PewPew Versions</Danger></VersionDivSelect>}
<Toaster id="toaster" message={toasterMessage}/>
</VersionDiv>
);
};
Expand Down
5 changes: 4 additions & 1 deletion controller/components/PewPewVersions/initialProps.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { LogLevel, log } from "@fs/ppaas-common";
import { getCurrentPewPewLatestVersion, getPewPewVersionsInS3 } from "../../pages/api/util/pewpew";
import { API_PEWPEW } from "../../types";
import { VersionInitalProps } from ".";
import { getPewPewVersionsInS3 } from "../../pages/api/util/pewpew";
import { latestPewPewVersion } from "../../pages/api/util/clientutil";

export const getServerSideProps = async (): Promise<VersionInitalProps> => {
try {
const pewpewVersions: string[] = await getPewPewVersionsInS3();
const currentPewPewLatestVersion: string | undefined = await getCurrentPewPewLatestVersion();
log("getPewPewVersionsInS3", LogLevel.DEBUG, pewpewVersions);
// Grab the response
// console.log("PewPewVersions pewpewVersions: " + JSON.stringify(pewpewVersions), pewpewVersions);
Expand All @@ -16,6 +17,7 @@ export const getServerSideProps = async (): Promise<VersionInitalProps> => {
return {
pewpewVersion: latestPewPewVersion, // We always want to default to latest
pewpewVersions,
latestPewPewVersion: currentPewPewLatestVersion || "unknown",
loading: false,
error: false
};
Expand All @@ -25,6 +27,7 @@ export const getServerSideProps = async (): Promise<VersionInitalProps> => {
return {
pewpewVersion: "",
pewpewVersions: [],
latestPewPewVersion: "unknown",
loading: false,
error: true
};
Expand Down
5 changes: 3 additions & 2 deletions controller/components/PewPewVersions/story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ const props: VersionProps = {
console.log("newVal: ", newVal);
},
pewpewVersions: ["0.1.1", "0.1.2", "0.1.3", "0.1.4", "0.1.5", latestPewPewVersion, "0.1.6"],
latestPewPewVersion: "0.1.6",
loading: false,
error: false
};
const propsLoading: VersionProps = { ...props, pewpewVersions: [], loading: true };
const propsError: VersionProps = { ...props, error: true };
const propsLoading: VersionProps = { ...props, pewpewVersions: [], latestPewPewVersion: "unknown", loading: true };
const propsError: VersionProps = { ...props, error: true, latestPewPewVersion: "unknown" };

export default {
title: "PewPewVersions"
Expand Down
2 changes: 1 addition & 1 deletion controller/components/StartTestForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export const StartTestForm = ({
allDays: defaultDaysOfWeek.every((dayOfWeek: DayValue) => dayOfWeek.value),
queueName: previousTestData?.queueName || queueInitialProps.queueName,
pewpewVersion: previousTestData?.version || (recurringTest ? maxPewPewVersion : versionInitalProps.pewpewVersion),
environmentVariables: previousTestData?.environmentVariables
environmentVariables: previousTestData?.environmentVariables
? Object.entries(previousTestData.environmentVariables).map(([variableName, variableValue]: [string, string | null], index: number) => ({
// Map these to the placeholder values
name: "previousVar" + index, // We can't use the date or we'll get constant redraws, use the index
Expand Down
2 changes: 2 additions & 0 deletions controller/components/StartTestForm/story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const versionInitalPropsEmpty: VersionInitalProps = {
pewpewVersion: "",
loading: false,
pewpewVersions: [],
latestPewPewVersion: "unknown",
error: true
};
const queueInitialProps: QueueInitialProps = {
Expand All @@ -50,6 +51,7 @@ const versionInitalProps: VersionInitalProps = {
pewpewVersion: "",
loading: false,
pewpewVersions: [latestPewPewVersion, "0.5.10", "0.5.11", "0.5.12"],
latestPewPewVersion: "0.5.12",
error: false
};
let ppaasTestId: PpaasTestId;
Expand Down
2 changes: 1 addition & 1 deletion controller/components/TestInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const TestInfo = ({ testData, ...testInfoProps }: TestInfoProps) => {
const defaultState: TestInfoState = {
message: testInfoProps.message || undefined,
messageId: testInfoProps.messageId || undefined,
killTest : testInfoProps.killTest || undefined,
killTest: testInfoProps.killTest || undefined,
error: testInfoProps.error || undefined
};
const [state, setState] = useState(defaultState);
Expand Down
49 changes: 49 additions & 0 deletions controller/components/Toaster/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React, { useEffect } from "react";
import styled, { keyframes } from "styled-components";
import { Info } from "../Alert";

interface ToasterProps {
message: string; // Ensure message prop is of type string
duration?: number;
id: string; // Unique ID for the toaster
}

// Fade-in animation
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;

// Fade-out animation
const fadeOut = keyframes`
from { opacity: 1; }
to { opacity: 0; }
`;

const Container = styled(Info)`
position: fixed;
bottom: 20px;
right: 20px;
width: 30%;
font-size: 17px;
animation: ${fadeIn} 0.3s ease-in-out forwards;
&.fade-out { animation: ${fadeOut} 0.3s ease-in-out forwards; }
`;

const Toaster: React.FC<ToasterProps> = ({ id, message, duration = 7000 }) => {
useEffect(() => {
setTimeout(() => {
const toasterElement = document.getElementById(id);
if (toasterElement) {
toasterElement.classList.add("fade-out");
setTimeout(() => {
toasterElement.remove();
}, 300); // Wait for fade-out animation to complete before removing element
}
}, duration);
}, [id, duration]);
return <Container id={id}>{message}</Container>;
};

export default Toaster;
16 changes: 16 additions & 0 deletions controller/components/Toaster/story.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryFn } from "@storybook/react";
import { GlobalStyle } from "../Layout";
import React from "react";
import Toaster from "./index";

export default {
title: "Toaster",
component: Toaster
} as Meta<typeof Toaster>;

export const Default: StoryFn = () => (
<React.Fragment>
<GlobalStyle />
<Toaster id="toaster" message={"Type your message here: "}/>
</React.Fragment>
);
74 changes: 65 additions & 9 deletions controller/integration/pewpew.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { AuthPermission, AuthPermissions, ErrorResponse, PewPewVersionsResponse, TestManagerError } from "../types";
import type { File, Files } from "formidable";
import { LogLevel, log, logger } from "@fs/ppaas-common";
import { ParsedForm, createFormidableFile, unzipFile } from "../pages/api/util/util";
import { deletePewPew, getPewPewVersionsInS3, getPewpew, postPewPew } from "../pages/api/util/pewpew";
import { LogLevel, PpaasS3File, log, logger } from "@fs/ppaas-common";
import { PEWPEW_BINARY_FOLDER, ParsedForm, createFormidableFile, unzipFile } from "../pages/api/util/util";
import { VERSION_TAG_NAME, deletePewPew, getCurrentPewPewLatestVersion, getPewPewVersionsInS3, getPewpew, postPewPew } from "../pages/api/util/pewpew";
import { expect } from "chai";
import { latestPewPewVersion } from "../pages/api/util/clientutil";
import path from "path";
Expand All @@ -22,6 +22,7 @@ const authAdmin: AuthPermissions = {

let sharedPewPewVersions: string[] | undefined;
let uploadedPewPewVersion: string | undefined; // Used for delete
let currentPewPewLatestVersion: string | undefined;

describe("PewPew Util Integration", () => {
let filesLegacyPewpew: Files = {};
Expand Down Expand Up @@ -101,7 +102,7 @@ describe("PewPew Util Integration", () => {
files: filesLegacyPewpew
};
log("postPewPew parsedForm", LogLevel.DEBUG, parsedForm);
postPewPew(parsedForm, authAdmin).then((res: ErrorResponse) => {
postPewPew(parsedForm, authAdmin).then(async (res: ErrorResponse) => {
log("postPewPew res", LogLevel.DEBUG, res);
expect(res.status, JSON.stringify(res.json)).to.equal(200);
const body: TestManagerError = res.json;
Expand All @@ -123,6 +124,21 @@ describe("PewPew Util Integration", () => {
sharedPewPewVersions.push(version);
}
log("sharedPewPewVersions: " + sharedPewPewVersions, LogLevel.DEBUG);
try {
const pewpewFiles = await PpaasS3File.getAllFilesInS3({
s3Folder: `${PEWPEW_BINARY_FOLDER}/${version}`,
localDirectory: process.env.TEMP || "/tmp"
});
expect(pewpewFiles).to.not.equal(undefined);
expect(pewpewFiles.length).to.be.greaterThan(0);
const pewpewFile = pewpewFiles.find( (file) => file.filename === "pewpew");
expect(pewpewFile).to.not.equal(undefined);
expect(pewpewFile?.tags).to.not.equal(undefined);
expect(pewpewFile?.tags?.get(VERSION_TAG_NAME)).to.equal(version);
} catch (error) {
log("postPewPew error while checking latest tag: ", LogLevel.ERROR, error);
throw error;
}
done();
}).catch((error) => {
log("postPewPew error", LogLevel.ERROR, error);
Expand All @@ -138,7 +154,7 @@ describe("PewPew Util Integration", () => {
files: filesLegacyPewpew
};
log("postPewPew parsedForm", LogLevel.DEBUG, parsedForm);
postPewPew(parsedForm, authAdmin).then((res: ErrorResponse) => {
postPewPew(parsedForm, authAdmin).then(async (res: ErrorResponse) => {
log("postPewPew res", LogLevel.DEBUG, res);
expect(res.status, JSON.stringify(res.json)).to.equal(200);
const body: TestManagerError = res.json;
Expand All @@ -147,14 +163,34 @@ describe("PewPew Util Integration", () => {
expect(body.message).to.not.equal(undefined);
expect(body.message).to.include("PewPew uploaded, version");
expect(body.message).to.include("as latest");
const version = latestPewPewVersion;
const match: RegExpMatchArray | null = body.message.match(/PewPew uploaded, version: (\d+\.\d+\.\d+)/);
log(`pewpew match: ${match}`, LogLevel.DEBUG, match);
expect(match, "pewpew match").to.not.equal(null);
expect(match!.length, "pewpew match.length").to.be.greaterThan(1);
const version: string = match![1];
// If this runs before the other acceptance tests populate the shared pewpew versions
if (!sharedPewPewVersions) {
sharedPewPewVersions = [version];
} else if (!sharedPewPewVersions.includes(version)) {
sharedPewPewVersions.push(version);
sharedPewPewVersions = [latestPewPewVersion];
} else if (!sharedPewPewVersions.includes(latestPewPewVersion)) {
sharedPewPewVersions.push(latestPewPewVersion);
}
log("sharedPewPewVersions: " + sharedPewPewVersions, LogLevel.DEBUG);
try {
const pewpewFiles = await PpaasS3File.getAllFilesInS3({
s3Folder: `${PEWPEW_BINARY_FOLDER}/${latestPewPewVersion}`,
localDirectory: process.env.TEMP || "/tmp"
});
expect(pewpewFiles).to.not.equal(undefined);
expect(pewpewFiles.length).to.be.greaterThan(0);
const pewpewFile = pewpewFiles.find( (file) => file.filename === "pewpew");
expect(pewpewFile).to.not.equal(undefined);
expect(pewpewFile?.tags).to.not.equal(undefined);
expect(pewpewFile?.tags?.get(VERSION_TAG_NAME)).to.equal(version);
} catch (error) {
log("postPewPew error while checking latest tag: ", LogLevel.ERROR, error);
throw error;
}
currentPewPewLatestVersion = version;
done();
}).catch((error) => {
log("postPewPew error", LogLevel.ERROR, error);
Expand Down Expand Up @@ -198,6 +234,20 @@ describe("PewPew Util Integration", () => {
});

describe("getPewpew", () => {
before(async () => {
try {
const pewpewFiles = await PpaasS3File.getAllFilesInS3({
s3Folder: `${PEWPEW_BINARY_FOLDER}/${latestPewPewVersion}`,
localDirectory: process.env.TEMP || "/tmp"
});
expect(pewpewFiles).to.not.equal(undefined);
const pewpewFile = pewpewFiles.find( (file) => file.filename === "pewpew");
expect(pewpewFile).to.not.equal(undefined);
} catch (error) {
log("getCurrentPewPewLatest Version failed: ", LogLevel.ERROR, error);
throw error;
}
});
it("getPewpew should respond 200 OK", (done: Mocha.Done) => {
expect(sharedPewPewVersions, "sharedPewPewVersions").to.not.equal(undefined);
getPewpew().then((res: ErrorResponse | PewPewVersionsResponse) => {
Expand All @@ -213,6 +263,12 @@ describe("PewPew Util Integration", () => {
done();
}).catch((error) => done(error));
});

it("getCurrentPewPewLatestVersion", async () => {
expect(currentPewPewLatestVersion, "currentPewPewLatestVersion").to.not.equal(undefined);
const result = await getCurrentPewPewLatestVersion();
expect(result, "result").to.equal(currentPewPewLatestVersion);
});
});

describe("deletePewPew", () => {
Expand Down
2 changes: 1 addition & 1 deletion controller/pages/admin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ const Admin = ({ authPermission, versionInitalProps, error: propsError }: AdminP

export const getServerSideProps: GetServerSideProps =
async (ctx: GetServerSidePropsContext): Promise<GetServerSidePropsResult<AdminProps>> => {
let versionInitalProps: VersionInitalProps = { pewpewVersion: "", loading: false, pewpewVersions: [], error: true };
let versionInitalProps: VersionInitalProps = { pewpewVersion: "", loading: false, pewpewVersions: [], latestPewPewVersion: "", error: true };
try {
// Authenticate
const authPermissions: AuthPermissions | string = await authPage(ctx, AuthPermission.Admin);
Expand Down
Loading

0 comments on commit 77a4464

Please sign in to comment.