Skip to content

Commit

Permalink
Merge pull request 1480 from develop
Browse files Browse the repository at this point in the history
Develop 1480
  • Loading branch information
bilalesi authored Jan 30, 2024
2 parents 9dc81d9 + b8ffaba commit 512b5a9
Show file tree
Hide file tree
Showing 24 changed files with 712 additions and 249 deletions.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ dist/
node_modules/
storybook-static/
coverage/
.vscode
yarn-error.log
cypress/screenshots/
cypress/videos/
Expand Down
6 changes: 6 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"recommendations": [
"editorconfig.editorconfig",
"christian-kohler.npm-intellisense"
]
}
25 changes: 25 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "Attach SPA debugging (frontend-only)",
"url": "http://localhost:8000",
"webRoot": "${workspaceFolder}"
},
{
"type": "node",
"request": "launch",
"name": "SRR debugging (full-stack)",
"runtimeExecutable": "node",
"runtimeArgs": ["--inspect-brk", "${workspaceFolder}/dist/server.js"],
"env": {
"NODE_ENV": "development",
"DEBUG": "*"
},
"console": "integratedTerminal",
"internalConsoleOptions": "openOnSessionStart"
}
]
}
4 changes: 4 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"editor.formatOnSave": true,
"files.eol": "\n"
}
Binary file added bun.lockb
Binary file not shown.
135 changes: 135 additions & 0 deletions cypress/e2e/ResourceContainer.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import { Resource } from '@bbp/nexus-sdk';

describe('Resource with id that contains URL encoded characters', () => {
const resourceIdWithEncodedCharacters =
'https://hello.lol/https%3A%2F%2Fencoded.url%2Fwow';
const displayName = 'https%3A%2F%2Fencoded.url%2Fwow';

before(() => {
if (
!Cypress.env('use_existing_delta_instance') ||
Cypress.env('use_existing_delta_instance') === false
) {
cy.task('auth:createRealmsAndUsers', Cypress.env('users'));
}

cy.login(
`${Cypress.env('users').morty.username}-studio`,
Cypress.env('users').morty.realm,
Cypress.env('users').morty.username,
Cypress.env('users').morty.password
).then(() => {
cy.window().then(win => {
const authToken = win.localStorage.getItem('nexus__token');
cy.wrap(authToken).as('nexusToken');

const orgLabel = Cypress.env('ORG_LABEL');
const projectLabelBase = Cypress.env('PROJECT_LABEL_BASE');

cy.task('project:setup', {
nexusApiUrl: Cypress.env('NEXUS_API_URL'),
authToken,
orgLabel,
projectLabelBase,
}).then(({ projectLabel }: { projectLabel: string }) => {
cy.wrap(projectLabel).as('projectLabel');
cy.fixture('ResourceWithEncodedCharactersId.json').then(
resourcePayload => {
cy.task('resource:create', {
nexusApiUrl: Cypress.env('NEXUS_API_URL'),
authToken,
orgLabel,
projectLabel,
resourcePayload,
}).then((resource: Resource) => {
cy.wrap(resource['@id']).as('fullResourceId');
});
}
);
});
});
});
});

beforeEach(() => {
cy.login(
`${Cypress.env('users').morty.username}-report-plugin`,
Cypress.env('users').morty.realm,
Cypress.env('users').morty.username,
Cypress.env('users').morty.password
);
});

after(function() {
cy.task('project:teardown', {
nexusApiUrl: Cypress.env('NEXUS_API_URL'),
authToken: this.nexusToken,
orgLabel: Cypress.env('ORG_LABEL'),
projectLabel: this.projectLabel,
});
});

function testResourceDataInJsonViewer() {
cy.findByText('Advanced View').click();

cy.contains(`"@id"`);
cy.contains(resourceIdWithEncodedCharacters);
cy.contains('type');
cy.contains('[]');
}

it('resource opens when user clicks on resource row in MyData table', function() {
cy.visit(`/`);

cy.findAllByText(new RegExp(displayName))
.first()
.click();

cy.findByTestId('resource-details').within(() => {
testResourceDataInJsonViewer();
});
});

it('resource opens when user directly navigates to resource page', function() {
const resourcePage = `/${Cypress.env('ORG_LABEL')}/${
this.projectLabel
}/resources/${encodeURIComponent(resourceIdWithEncodedCharacters)}`;

cy.visit(`${resourcePage}`);

cy.findByTestId('resource-details').within(() => {
testResourceDataInJsonViewer();
});
});

it('resource opens with id resolution page', function() {
const resolvePage = `/resolve/${encodeURIComponent(
resourceIdWithEncodedCharacters
)}`;
const resourcePage = `/${Cypress.env('ORG_LABEL')}/${
this.projectLabel
}/resources/${encodeURIComponent(resourceIdWithEncodedCharacters)}`;

cy.visit(resolvePage);

cy.intercept(`${Cypress.env('NEXUS_API_URL')}/${resolvePage}`).as(
'idResolution'
);

// If many e2e tests ran together there may be many resources with same id.
// In this case the id resolution page will look different. Test accordingly.
cy.wait('@idResolution').then(interception => {
const resolvedResources = interception.response.body._results;

if (resolvedResources.length === 1) {
testResourceDataInJsonViewer();
} else {
// Multiple resources with same id found.
cy.findByText('Open Resource', {
selector: `a[href="${resourcePage}"]`,
}).click();
testResourceDataInJsonViewer();
}
});
});
});
4 changes: 4 additions & 0 deletions cypress/fixtures/ResourceWithEncodedCharactersId.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"@id": "https://hello.lol/https%3A%2F%2Fencoded.url%2Fwow",
"@type": []
}
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"express-prom-bundle": "^5.0.2",
"git-revision-webpack-plugin": "^3.0.6",
"handlebars": "^4.7.7",
"history": "^4.7.2",
"history": "4.5.1",
"http-proxy-middleware": "^2.0.1",
"json2csv": "^5.0.5",
"jwt-decode": "^2.2.0",
Expand Down Expand Up @@ -240,5 +240,8 @@
"webpack-hot-middleware": "^2.24.3",
"webpack-node-externals": "^1.7.2"
},
"resolutions": {
"history": "4.5.1"
},
"url": "https://github.com/BlueBrain/nexus/issues/new?labels=fusion"
}
102 changes: 102 additions & 0 deletions src/__mocks__/handlers/ResourceListContainerHandlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import { rest } from 'msw';
import { deltaPath } from '__mocks__/handlers/handlers';
import { Resource } from '@bbp/nexus-sdk';

export const resourcesHandler = rest.get(
deltaPath(`resources/bbp/agents`),
(_, res, ctx) => {
const mockResponse = {
'@context': ['https://bluebrain.github.io/nexus/contexts/metadata.json'],
_total: 3,
_results: [
getMockResource('1'),
getMockResource('2'),
getMockResource('3'),
],
};

return res(ctx.status(200), ctx.json(mockResponse));
}
);

export const searchHitsHandler = rest.post(
deltaPath(
'/views/bbp/agents/https%3A%2F%2Fbluebrain.github.io%2Fnexus%2Fvocabulary%2FdefaultElasticSearchIndex/_search'
),
(_, res, ctx) => {
const filteredByDeprecation = {
buckets: [getMockBucket('1'), getMockBucket('2'), getMockBucket('3')],
doc_count_error_upper_bound: 0,
sum_other_doc_count: 0,
};
const mockResponse = {
aggregations: {
schemas: {
doc_count: 3,
filteredByDeprecation: { ...filteredByDeprecation },
},
types: {
doc_count: 8,
filteredByDeprecation: { ...filteredByDeprecation },
},
},
hits: {
hits: [
getMockSearchHit('1'),
getMockSearchHit('2'),
getMockSearchHit('3'),
],
max_score: 123,
total: { relation: 'eq', value: 11 },
},
timed_out: false,
took: 0,
_shards: { failed: 0, skipped: 0, successful: 1, total: 1 },
};

return res(
// Respond with a 200 status code
ctx.status(200),
ctx.json(mockResponse)
);
}
);

const getMockResource = (id: string, extra?: Partial<Resource>) => ({
'@id': id,
'@type': ['View'],
description: 'Test description',
name: 'Test name',
_constrainedBy: 'https://bluebrain.github.io/nexus/schemas/views.json',
_createdAt: '2024-01-19T11:40:24.804553Z',
_createdBy: 'https://bbp.epfl.ch/nexus/v1/realms/bbp/users/mockuser',
_deprecated: false,
_incoming: 'test',
_outgoing: 'test',
_project: 'https://dev.nise.bbp.epfl.ch/nexus/v1/projects/bbp/agents',
_rev: 1,
_self: id,
_updatedAt: '2024-01-19T11:40:24.804553Z',
_updatedBy: 'https://bbp.epfl.ch/nexus/v1/realms/bbp/users/mockuser',
_uuid: id,
...extra,
});

const getMockSearchHit = (id: string, extra?: Partial<Resource>) => {
const resource = getMockResource(id, extra);
return {
_id: id,
_index: `delta_${id}`,
_score: 123,
_source: {
...resource,
_original_source: JSON.stringify(resource),
},
_type: '_doc',
};
};

const getMockBucket = (key: string, docCount: number = 1) => ({
key,
doc_count: docCount,
});
2 changes: 1 addition & 1 deletion src/shared/components/ResourceActions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as React from 'react';
import { Tooltip, Button, Popconfirm } from 'antd';
import { Resource } from '@bbp/nexus-sdk';
import useNotification from '../../hooks/useNotification';

import './ResourceActions.less';
import useNotification from '../../hooks/useNotification';

export type ActionType = {
name: string; // A unique name for your action type
Expand Down
Loading

0 comments on commit 512b5a9

Please sign in to comment.