diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..e7e1fb04 --- /dev/null +++ b/.eslintignore @@ -0,0 +1 @@ +tests/* diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..0fb8699e --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + "root": true +} diff --git a/.gitignore b/.gitignore index 87ca27ec..20a5d7db 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,9 @@ coverage/*.xml Pipfile Pipfile.lock + +# Test output files +tests/N1.mdx +tests/N2.mdx +tests/S1.mdx +tests/provision.js diff --git a/scripts/preprocess.py b/scripts/preprocess.py index 199ad994..5d555d2d 100644 --- a/scripts/preprocess.py +++ b/scripts/preprocess.py @@ -60,7 +60,7 @@ class Preprocess: - def __init__(self, args, is_test=False): + def __init__(self, args, is_test=False): # pragma: no cover self.node_to_meta = {} self.provider_to_meta = {} self.variants = {} @@ -185,7 +185,7 @@ def generate_graph(self, lines: iter) -> tuple: self.node_to_meta[child][node_type].append(parent) return graph, graph_reverse - def write_graphs(self, sequence: str, output_dir: str) -> None: + def write_graphs(self, sequence: str, output_dir: str) -> None: # pragma: no cover """ Parses a csv that specifies node type, the edges between nodes, and node variants :param sequence: sequence csv @@ -425,7 +425,9 @@ def _get_node_to_country_provision(self): node_to_country_provision[node]["all_names"].sort() return node_to_country_provision - def _get_country_provision_graph(self, graph, output_dir, node_id): + def _get_country_provision_graph( + self, graph, output_dir, node_id + ): # pragma: no cover """ Generate a graph representing country provisions for a node :return: A dictionary representation of a graph @@ -544,7 +546,9 @@ def _mk_pdf_for_node( {"enable-local-file-access": None}, ) - def mk_pdfs(self, nodes_fi: str, stages_fi: str, output_dir: str) -> None: + def mk_pdfs( + self, nodes_fi: str, stages_fi: str, output_dir: str + ) -> None: # pragma: no cover """ Generate pdf version of the each node's description :param nodes_fi: CSV file with node information @@ -631,7 +635,7 @@ def write_provider_bq_table(self, provider_fi: str): writer.writerow(line) return provider_bq_fi - def write_to_bq(self, nodes_fi, provider_bq_fi): + def write_to_bq(self, nodes_fi, provider_bq_fi): # pragma: no cover """ Load CSVs to bigquery tables, overwriting the existing tables. Also loads the CSVs to versioned backup tables. diff --git a/supply-chain/.eslintrc.js b/supply-chain/.eslintrc.js index a8f09ae9..9d27fe78 100644 --- a/supply-chain/.eslintrc.js +++ b/supply-chain/.eslintrc.js @@ -1,6 +1,7 @@ module.exports = { "globals": { __PATH_PREFIX__: true, + "fetchMock": true, }, "env": { "browser": true, @@ -12,6 +13,6 @@ module.exports = { ], "parserOptions": { "ecmaVersion": "latest", - "sourceType": "module" + "sourceType": "module", }, } diff --git a/supply-chain/jest.config.js b/supply-chain/jest.config.js index 4baea8c1..4df12f68 100644 --- a/supply-chain/jest.config.js +++ b/supply-chain/jest.config.js @@ -20,6 +20,7 @@ module.exports = { collectCoverage: true, collectCoverageFrom: [ 'src/**/*.{js,jsx}', + '!src/pages/*', '!**/__tests__/**', ], // TBD - we have not decided on these yet diff --git a/supply-chain/src/components/__tests__/dashboard.js b/supply-chain/src/components/__tests__/dashboard.js index 632f0125..3abc0c1b 100644 --- a/supply-chain/src/components/__tests__/dashboard.js +++ b/supply-chain/src/components/__tests__/dashboard.js @@ -23,6 +23,18 @@ describe("Gradient Legend", () => { }); describe("Dashboard", () => { + beforeEach(() => { + window.HTMLElement.prototype.scrollIntoView = function() {}; + const location = { + ...window.location, + search: '', + }; + Object.defineProperty(window, 'location', { + writable: true, + value: location, + }); + }) + it("renders correctly", () => { const {asFragment} = render(); expect(asFragment()).toMatchSnapshot(); @@ -64,6 +76,25 @@ describe("Dashboard", () => { expect(screen.getAllByText("Crystal growing furnaces").length).toEqual(1); }); + it("opens a documentation node with variants and subvariants", () => { + render(); + // Click on a node with subvariants + fireEvent.click(screen.getByText("Deposition tools")); + fireEvent.click(screen.getAllByText("Chemical vapor deposition tools")[0]); + + // Show subvariants list + expect(screen.getAllByText("Atomic layer deposition tools").length).toEqual(5); + }); + + it("opens a stage node", () => { + render(); + // Click on a stage node title + fireEvent.click(screen.getByText("Fabrication")); + + // Show stage node text + expect(screen.getByText("at the 45 nm node or below", {exact: false})).not.toBeNull(); + }); + it("changes the highlighting shown", () => { render(); // Initially, the nodes are not highlighted diff --git a/tests/test_N1.mdx b/tests/test_N1.mdx new file mode 100644 index 00000000..14435e36 --- /dev/null +++ b/tests/test_N1.mdx @@ -0,0 +1,3 @@ +#### Logic chip design: Advanced CPUs + +Central processing units ("CPUs") are the dominant general purpose logic chips. Two U.S. firms, Intel and AMD, have long held a duopoly over CPUs used for laptops, desktops, and servers. (China has several ventures, though none are competitive with U.S. firms.) CPUs are often classified into "nodes," which represent technology generations: a chip at a new node (e.g., "5 nm‚" released in 2020) contains approximately double the transistor density as a previous node (e.g., "7 nm‚" released in 2018) and is also more cost-effective. diff --git a/tests/test_preprocess.py b/tests/test_preprocess.py index 0976176f..d9b08776 100644 --- a/tests/test_preprocess.py +++ b/tests/test_preprocess.py @@ -64,6 +64,7 @@ def test_mk_metadata(self): def test_mk_provider_to_meta(self): self.maxDiff = None provider_fi = "./tests/test_providers.csv" + provision_fi = "./tests/test_provision.csv" pp = Preprocess(None, True) pp.mk_provider_to_meta(provider_fi) self.assertEqual( @@ -92,6 +93,12 @@ def test_mk_provider_to_meta(self): }, }, ) + pp.write_provision(provision_fi, "tests/") + + output_truth = open("tests/test_provision.js").read() + output_testing = open("tests/provision.js").read() + + self.assertEqual(output_testing, output_truth) def test_get_flag(self): self.assertEqual("🇺🇸", Preprocess.get_flag("USA")) @@ -319,3 +326,14 @@ def test_clean_md_link(self): "Flickr user [FritzchensFritz](https://www.flickr.com/photos/130561288@N04/50914099198/)" ), ) + + def test_write_descriptions(self): + pp = Preprocess(None, True) + pp.write_descriptions( + "./tests/test_input.csv", "./tests/test_stages.csv", "tests/" + ) + + output_truth = open("tests/test_N1.mdx").read().strip() + output_testing = open("tests/N1.mdx").read().strip() + + self.assertEqual(output_testing, output_truth) diff --git a/tests/test_provision.csv b/tests/test_provision.csv new file mode 100644 index 00000000..be9808a9 --- /dev/null +++ b/tests/test_provision.csv @@ -0,0 +1,3 @@ +provider_name,provider_id,provided_name,provided_id,share_provided,negligible_market_share +USA,P1,Design,S1,61%, +USA,P1,Fabrication,S2,27%, diff --git a/tests/test_provision.js b/tests/test_provision.js new file mode 100644 index 00000000..ed36b1fa --- /dev/null +++ b/tests/test_provision.js @@ -0,0 +1,8 @@ +const countryProvision={"United States": {"S1": 61, "S2": 27}}; +const countryFlags={"United States": "\ud83c\uddfa\ud83c\uddf8"}; +const countryProvisionConcentration={"S1": 1, "S2": 1}; +const orgProvision={}; +const processNodesWithOrgProvision=[]; +const providerMeta={"P1": {"name": "USA", "type": "country"}, "P2": {"name": "CHN", "type": "country"}, "P4": {"name": "KOR", "type": "country"}, "P9": {"name": "Intel", "type": "organization", "hq_flag": "\ud83c\uddfa\ud83c\uddf8", "hq_country": "United States"}, "P10": {"name": "AMD", "type": "organization", "hq_flag": "\ud83c\uddfa\ud83c\uddf8", "hq_country": "United States"}, "P15": {"name": "Phytium", "type": "organization", "hq_flag": "\ud83c\udde8\ud83c\uddf3", "hq_country": "China (mainland)"}}; + +export {countryProvision, countryFlags, countryProvisionConcentration, orgProvision, processNodesWithOrgProvision, providerMeta};