8 changed files with 75 additions and 287 deletions
-187
View File
@@ -1,187 +0,0 @@
# Analisi repository API Collections
## Esito
Il repository ha unarchitettura semplice e appropriata allo scopo, ma la pipeline Bruno → httpyac non è sufficientemente protetta. I rischi principali sono:
1. esempi versionati contenenti dati personali e identificativi di sessione;
2. conversioni httpyac incomplete o incompatibili;
3. tre file YAML non validi per il parser usato dal progetto;
4. test e quality gate quasi assenti.
Non serve una riscrittura generale: gli interventi possono essere incrementali e concentrati sui confini di conversione e validazione.
## Struttura e dipendenze
```text
bruno/workspace.yml
└─ 11 collezioni Bruno / 272 richieste circa
├─ folder e configurazioni ereditate
├─ ambienti e template dei segreti
├─ script Bruno
└─ esempi di request/response versionati
env.json.template
└─ setup-json-environment.ps1 → env.json locale
├─ update-bruno-environments.ps1 → .env Bruno
└─ update-httpyac-environments.ps1 → .env httpyac
bruno/
└─ generate-httpyac-requests.ps1 → autodocs/httpyac/ ignorato da Git
```
Dipendenze esterne:
- PowerShell ≥ 7.5;
- modulo `powershell-yaml`, disponibile localmente in versione 0.4.12;
- Bruno;
- estensione/CLI httpyac, non disponibile nella shell esaminata.
`tools/generate-http-requests/node_modules` è un artefatto locale ignorato, senza manifest versionato, e non costituisce una dipendenza riproducibile del repository.
## Quality gate e test attuali
Non risultano configurati CI, Pester, PSScriptAnalyzer, linting, coverage, scansione dei segreti o validazione automatica delle collezioni.
Controlli read-only eseguiti:
- 5 script PowerShell analizzati: zero errori sintattici;
- 338 file YAML analizzati con `powershell-yaml`;
- 3 YAML non validi;
- 269 richieste analizzabili: 129 GET, 118 POST, 17 PUT, 3 DELETE, 2 PATCH;
- 140 richieste mutative analizzabili;
- solo 4 delle 140 richieste mutative hanno una definizione di test a livello di richiesta;
- i 7 `.env.template` sono attualmente sincronizzati con `env.json.template`;
- nessuna suite automatizzata eseguibile;
- PSScriptAnalyzer e httpyac CLI non presenti.
Gli `examples` presenti nelle collezioni sono snapshot, non test. Lo stato complessivo dei gate è quindi **non superato/non definito**: manca un gate ufficiale e la validazione YAML già fallisce.
## Backlog tecnico prioritizzato
Costo indicativo: **S** < 1 giorno, **M** 13 giorni, **L** > 3 giorni.
### 1. Dati personali e cookie di sessione negli esempi versionati
- **Severità/costo:** Critica / M
- **File/modulo:** esempi Bruno, per esempio [Get Items.yml](<C:/_Git/UniPR/api-collections/bruno/collections/IRIS GW (Gateway) REST API (v1)/WfItems/Get Items.yml:136>) e [Get UserInfo.yml](<C:/_Git/UniPR/api-collections/bruno/collections/Shibboleth/Get UserInfo.yml:76>).
- **Problema:** rilevati identificativi compatibili con codici fiscali in 38 file e cookie/session ID in 20 file. Alcuni esempi includono anche nomi e informazioni organizzative. Il file più grande supera 5,3 MB e 134.000 righe.
- **Rischio:** esposizione di dati personali, conservazione indefinita nella cronologia Git, possibili credenziali di sessione ancora utilizzabili, forte rumore nelle review.
- **Intervento minimo:** verificare lorigine dei dati, invalidare eventuali sessioni ancora valide, redigere o sostituire con dati sintetici gli esempi; limitare gli snapshot alle proprietà indispensabili.
- **Test prima dellintervento:** introdurre una scansione ripetibile per cookie, token e identificativi personali con allowlist esplicita; registrare il baseline prima della redazione.
- **Impatto architetturale:** trasversale sulla politica di gestione degli esempi, senza nuovi layer.
### 2. Tre collezioni non sono parseabili dal convertitore dichiarato
- **Severità/costo:** Alta / S
- **File/modulo:** [Backoffice - Dashboard.yml](<C:/_Git/UniPR/api-collections/bruno/collections/elixForms API v2/Console UI/Backoffice - Dashboard.yml:125>), [Login - Backoffice.yml](<C:/_Git/UniPR/api-collections/bruno/collections/elixForms API v2/Console UI/Login - Backoffice.yml:172>), [Login - Gestione Schede.yml](<C:/_Git/UniPR/api-collections/bruno/collections/elixForms API v2/Console UI/Login - Gestione Schede.yml:140>).
- **Problema:** i literal block contengono righe iniziali whitespace-only che `powershell-yaml` rifiuta. Il generatore propaga lerrore da [Parse-Yaml](C:/_Git/UniPR/api-collections/scripts/generate-httpyac-requests.ps1:26).
- **Rischio:** generazione httpyac interrotta e output parziale o obsoleto.
- **Intervento minimo:** normalizzare quei blocchi e fare fallire il comando con un riepilogo completo dei file invalidi.
- **Test prima dellintervento:** gate che esegua il parsing di tutti i YAML; fixture con il blocco problematico e verifica dellerrore diagnostico.
- **Impatto architetturale:** nessuno; rende affidabile il formato sorgente.
### 3. Script Bruno copiati in httpyac senza adattamento del runtime
- **Severità/costo:** Alta / M
- **File/modulo:** [Parse-HttpBlock](C:/_Git/UniPR/api-collections/scripts/generate-httpyac-requests.ps1:206) e [Build-RequestContent](C:/_Git/UniPR/api-collections/scripts/generate-httpyac-requests.ps1:738).
- **Problema:** 16 file `.http` generati contengono chiamate Bruno come `bru.setVar` e `res.getStatus()`. httpyac documenta invece oggetti quali `response`, `$global` ed `exports`; la copia verbatim attraversa impropriamente il confine tra due runtime diversi. [Documentazione ufficiale httpyac](https://httpyac.github.io/guide/scripting.html)
- **Rischio:** request apparentemente generate ma script e test non eseguibili.
- **Intervento minimo:** tradurre solo le API Bruno effettivamente usate oppure interrompere esplicitamente la conversione dei file non supportati, evitando output silenziosamente difettoso.
- **Test prima dellintervento:** golden test per login, lettura risposta e salvataggio variabile; esecuzione del `.http` generato contro un endpoint mock.
- **Impatto architetturale:** importante sul boundary Bruno→httpyac, ma confinato alladapter esistente.
### 4. I body `multipart-form` vengono ignorati
- **Severità/costo:** Alta / M
- **File/modulo:** [Build-RequestContent](C:/_Git/UniPR/api-collections/scripts/generate-httpyac-requests.ps1:693); richieste interessate includono [AJ Console - Save Object.yml](<C:/_Git/UniPR/api-collections/bruno/collections/elixForms API v2/Console UI/AJ Console - Save Object.yml:15>), [Backoffice - Create Group.yml](<C:/_Git/UniPR/api-collections/bruno/collections/elixForms API v2/Console UI/Backoffice - Create Group.yml:16>) e Login Backoffice.
- **Problema:** il generatore implementa soltanto `json` e `form-urlencoded`; per multipart emette una POST senza body e senza segnalazione.
- **Rischio:** operazioni mutative errate, con comportamento molto diverso dalla richiesta Bruno.
- **Intervento minimo:** supportare multipart per i campi realmente presenti oppure fallire esplicitamente indicando request e body type.
- **Test prima dellintervento:** fixture multipart con campi testo, placeholder e caratteri speciali; confronto golden del body generato.
- **Impatto architetturale:** locale al convertitore.
### 5. Aree mutative quasi prive di protezione automatica
- **Severità/costo:** Alta / L
- **File/modulo:** soprattutto `Cambio stato e-o integrazione`, `Console UI`, ESSE3 e i 93 POST EFTL.
- **Problema:** soltanto 4 delle 140 richieste mutative analizzabili hanno test request-level; non esiste un comando CI che li esegua.
- **Rischio:** regressioni su cambio stato, clone, aggiornamenti, delete e autenticazione scoperte soltanto manualmente.
- **Intervento minimo:** partire da smoke/contract test per autenticazione e operazioni più distruttive, usando ambienti controllati o mock; non è necessario testare subito ogni snapshot.
- **Test prima dellintervento:** definire una matrice minima per status, payload obbligatori, errori 4xx e assenza di effetti collaterali indesiderati.
- **Impatto architetturale:** introduce un gate, non un nuovo layer applicativo.
### 6. Serializzazione `.env` non round-trip safe
- **Severità/costo:** Alta / S
- **File/modulo:** [update-bruno-environments.ps1](C:/_Git/UniPR/api-collections/scripts/update-bruno-environments.ps1:29) e [update-httpyac-environments.ps1](C:/_Git/UniPR/api-collections/scripts/update-httpyac-environments.ps1:26).
- **Problema:** i valori contenenti `#` vengono quotati, ma il parser conserva le quote; una seconda esecuzione può produrre quote duplicate. Apici, newline e altri caratteri dotenv non vengono gestiti sistematicamente.
- **Rischio:** password e token validi diventano inutilizzabili senza errore esplicito.
- **Intervento minimo:** definire escaping e parsing simmetrici per il sottoinsieme dotenv supportato.
- **Test prima dellintervento:** round-trip parametrico per `#`, apici, spazi, `=`, valori vuoti e `null`.
- **Impatto architetturale:** boundary dei segreti; nessun nuovo layer necessario.
### 7. Test errato e dead code nello script “owners”
- **Severità/costo:** Media / S
- **File/modulo:** [SCRIPT - Get Contracts with two or more owners.yml](<C:/_Git/UniPR/api-collections/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml:113>).
- **Problema:** loutput espone `ownersCount`, ma il test verifica `contributorCount` alla [riga 248](<C:/_Git/UniPR/api-collections/bruno/collections/IRIS GW (Gateway) REST API (v1)/Contracts/SCRIPT - Get Contracts with two or more owners.yml:248>). Il controllo `output.length >= 0` alla riga 258 è tautologico. Rimane inoltre un intero ramo contributor commentato e una funzione department non più utilizzata.
- **Rischio:** fallimenti ingannevoli o test che passano senza verificare laggregazione; manutenzione confusa.
- **Intervento minimo:** correggere la proprietà, usare una fixture non vuota e rimuovere il ramo commentato dopo aver verificato che non sia necessario.
- **Test prima dellintervento:** dataset con zero, uno e più owners e paginazione multipla.
- **Impatto architetturale:** nessuno; elimina una conseguenza concreta del copy/paste.
### 8. Generatore troppo concentrato e accoppiato al nome della cartella EFTL
- **Severità/costo:** Media / M
- **File/modulo:** [generate-httpyac-requests.ps1](C:/_Git/UniPR/api-collections/scripts/generate-httpyac-requests.ps1:420).
- **Problema:** 1.095 righe; `Build-RequestContent` è di 377 righe con circa 63 diramazioni. Il comportamento EFTL è attivato cercando `"EFTL processing"` nel percorso e sovrascrive indiscriminatamente il post-response script alle [righe 733785](C:/_Git/UniPR/api-collections/scripts/generate-httpyac-requests.ps1:733). Inoltre `Parse-Workspace` reimplementa manualmente il parsing pur essendo già disponibile il parser YAML.
- **Rischio:** cambiamenti locali producono regressioni trasversali; rinominare una cartella cambia la semantica.
- **Intervento minimo:** aggiungere test di caratterizzazione e separare soltanto rendering di auth, body e script in funzioni pure; rendere esplicita la modalità EFTL nella configurazione.
- **Test prima dellintervento:** golden test EFTL/non-EFTL, inclusi script senza marker o marker incompleti.
- **Impatto architetturale:** chiarisce il confine tra conversione generica e regola EFTL senza introdurre pattern ulteriori.
### 9. Duplicazione degli updater e variabili dipendenti da rami precedenti
- **Severità/costo:** Media / M
- **File/modulo:** i due `update-*-environments.ps1`, differenti per appena 15 aggiunte e 18 rimozioni.
- **Problema:** `$sectionKeys` viene inizializzata dentro il ramo che trova `.env.template`, ma può essere usata successivamente anche quando il template manca. La duplicazione rende facile correggere un solo updater.
- **Rischio:** chiavi mancanti, riuso accidentale dei valori delliterazione precedente e divergenza Bruno/httpyac.
- **Intervento minimo:** prima inizializzare sempre le chiavi; poi usare ununica funzione parametrizzata per root e policy di esclusione.
- **Test prima dellintervento:** template presente/assente, `.env` presente/assente, chiavi aggiunte/rimosse e valori `null`.
- **Impatto architetturale:** riduce duplicazione di conoscenza nella pipeline dei segreti.
### 10. Bootstrap delle dipendenze non riproducibile
- **Severità/costo:** Media / S
- **File/modulo:** [setup-tools.ps1](C:/_Git/UniPR/api-collections/scripts/setup-tools.ps1:1) e [README.md](C:/_Git/UniPR/api-collections/README.md:18).
- **Problema:** il README promette un tentativo di installazione, ma lo script esegue solo `Import-Module ... -ErrorAction SilentlyContinue` e comunica comunque successo. Non è dichiarata una versione compatibile.
- **Rischio:** una nuova workstation fallisce più avanti con diagnostica poco chiara.
- **Intervento minimo:** verificare presenza/versione e terminare con istruzioni esplicite oppure installare soltanto previo consenso dellutente.
- **Test prima dellintervento:** esecuzione in una sessione senza modulo e con versione incompatibile.
- **Impatto architetturale:** dependency hygiene, nessun cambiamento strutturale.
### 11. Copie e contenuti obsoleti aumentano il rischio di deriva
- **Severità/costo:** Bassa / SM
- **File/modulo:** directory `OLD`, `Obsolete`, file `Get Items Copy.yml`/`Get ASNs Copy.yml` e due coppie di runner completamente identiche.
- **Problema:** duplicazione significativa e snapshot molto grandi; non è però dimostrabile dalla sola analisi statica che siano davvero inutilizzati.
- **Rischio:** correzioni applicate a una sola copia, review lente e crescita del repository.
- **Intervento minimo:** censire uso e ownership; eliminare solo copie confermate inutilizzate o documentarne esplicitamente lo scopo.
- **Test prima dellintervento:** confronto comportamentale delle copie e verifica con gli utilizzatori.
- **Impatto architetturale:** nessuno; pulizia controllata, non refactoring speculativo.
## Invarianti consigliate
I futuri gate dovrebbero verificare almeno che:
- ogni YAML sia parseabile dal parser effettivamente usato;
- nessun body type venga ignorato silenziosamente;
- gli script attraversino Bruno→httpyac solo se tradotti o dichiarati compatibili;
- gli output generati siano prodotti in una directory temporanea e validati;
- i template dei segreti restino sincronizzati;
- esempi e snapshot non contengano credenziali o dati personali non autorizzati.
Non raccomando al momento un ADR formale: basterebbe documentare queste invarianti nel repository e automatizzarle.
Non ho letto il contenuto di `env.json`, non ho eseguito chiamate API e non ho lanciato script che scrivono output. `git status` e `git diff` sono rimasti vuoti: nessun file è stato modificato.
@@ -11,7 +11,7 @@ http:
value: XMLHttpRequest value: XMLHttpRequest
params: params:
- name: request_id - name: request_id
value: "7007" value: "27547"
type: path type: path
body: body:
type: form-urlencoded type: form-urlencoded
@@ -19,17 +19,16 @@ http:
- name: username - name: username
value: "{{elixFormsApiUsername}}" value: "{{elixFormsApiUsername}}"
- name: outcome - name: outcome
value: OK value: KO
description: OK, KO description: OK, KO
- name: resultCode - name: resultCode
value: VAL value: KO
description: 'possibili valori: VAL("Validata"), IMP("Importata"), IMPW("Impostata con warning"), KO("Rifiutata")' description: 'possibili valori: VAL("Validata"), IMP("Importata"), IMPW("Impostata con warning"), KO("Rifiutata")'
- name: resultDescription - name: resultDescription
value: "" value: messaggio custom
description: descrizione esito processo esterno description: descrizione esito processo esterno
disabled: true
- name: resultReceiptId - name: resultReceiptId
value: "123" value: "999"
description: id pratica processo esterno di riferimento description: id pratica processo esterno di riferimento
- name: resultTimestamp - name: resultTimestamp
value: "" value: ""
@@ -136,8 +135,34 @@ examples:
} }
} }
docs: |- docs: |
Viene ritornato l'esito dell'operazione di storicizzazione si elixForms©. # Acquisizione delle istanze elaborate da processo esterno
La ricezione di "ok" o "ko" provocherà una decisione nel workflow semplice (analogo a quello di elixFlow©) in base a quanto disposto in elixForms per il modulo.
Esempio="OK","VAL","..." imposta lo stato di workflow semplice corrispondente imposta lo step ad "evasa" notifica email ~~Scopo: per confermare che l'istanza é stata ricevuta e non andrà più trasmessa.~~
Esempio="KO","KO","..." imposta lo stato di workflow semplice corrispondente non cambia lo stato dello step **(MA ASSOLUTAMENTE NO!)**
Empiricamente, sposta l'istanza in stato "Evasa" e impedisce la riapertura della stessa.
## Parametri importanti
- **outcome(*)** (esito del servizio): possibili valori:
- OK
- KO
- **resultCode(*)** (codice esito processo esterno): possibili valori:
- VAL("Validata")
- IMP("Importata")
- IMPW("Impostata con warning")
- KO("Rifiutata")
- **resultDescription** (descrizione esito processo esterno)
- **resultReceiptId(*)** (id pratica processo esterno di riferimento)
- **resultTimestamp**: (timestamp di riferimento dell'elaborazione pratica dal processo esterno): in formato standard ISO 8601; se non impostata viene inizializzata con la data/ora server corrente
- **properties** (mappa chiave,valore/i aggiuntivo/i in formato json): url-encoding richiesto in UTF-8
## Descrizione
Viene ritornato l'esito dell'operazione di storicizzazione su elixForms.
La ricezione di "ok" o "ko" provocherà una decisione nel workflow semplice (analogo a quello di elixFlow) in base a quanto disposto in elixForms per il modulo.
- Esempio="OK","VAL","..." imposta lo stato di workflow semplice corrispondente imposta lo step ad "evasa" notifica email
- Esempio="KO","KO","..." imposta lo stato di workflow semplice corrispondente non cambia lo stato dello step
@@ -5,7 +5,7 @@ info:
http: http:
method: POST method: POST
url: "{{elixFormsApiUrl_Default}}/request/:request_id/swf/columns;{{elixRegisterResultColumns}}?username={{elixFormsApiUsername}}" url: "{{elixFormsApiUrl_Default}}/request/:request_id/swf/{{columns}}?username={{elixFormsApiUsername}}"
headers: headers:
- name: x-requested-with - name: x-requested-with
value: XMLHttpRequest value: XMLHttpRequest
@@ -14,12 +14,18 @@ http:
value: "{{elixFormsApiUsername}}" value: "{{elixFormsApiUsername}}"
type: query type: query
- name: request_id - name: request_id
value: "6085" value: "27310"
type: path type: path
body:
type: form-urlencoded
auth: inherit auth: inherit
runtime:
variables:
- name: columns
value: ""
disabled: true
- name: columns
value: COL0001="1";COL0002={{$isoTimestamp}}
settings: settings:
encodeUrl: true encodeUrl: true
timeout: 0 timeout: 0
@@ -103,12 +109,13 @@ examples:
} }
docs: |- docs: |-
The elixRegisterResultColumns variable must be built like the following: The columns variable must be built like the following:
- one index=value couple for every field in the SWF schema that must be updated, where index is the "name" of the schema field (e.g.: COL0003, if the field is found in the SWF schema) and the value is the string content that must be assigned - variable must start with "columns;"
- add one "index=value" couple for every field in the SWF schema to be updated, where "index" is the name of the associated SWF schema field (e.g.: COL0003) and "value" is the string content to be used
- each couple must be separated by a semi-period (\`;\` character) - each couple must be separated by a semi-period (\`;\` character)
For example, suppose the request has a SWF schema with ID 356, containing: For example, suppose the request has a SWF schema with ID 356 having:
- State = COL0001 - State = COL0001
- Date = COL0002 - Date = COL0002
@@ -117,6 +124,8 @@ docs: |-
If you want to change the CURRENT state's date and message values, you will put into the variable the following value: If you want to change the CURRENT state's date and message values, you will put into the variable the following value:
`columns;[{"key":"COL0002","value":"31-03-2025"},{"key":"COL0004","value":"this is the new message"}]`
`COL0002=31-03-2025;COL0004=this is the new message` `COL0002=31-03-2025;COL0004=this is the new message`
Keep in mind that Postman automatically encodes the parameter, so it's allowed to use spaces and other symbols (maybe?). Keep in mind that Bruno automatically encodes the parameter, so you may use spaces and other symbols (maybe?).
@@ -44,13 +44,6 @@ runtime:
[% percentualeEcoFondo = ritenutaEcoFondo * 100; %] [% percentualeEcoFondo = ritenutaEcoFondo * 100; %]
[% percentualeEcoWelfare = ritenutaEcoWelfare * 100; %] [% percentualeEcoWelfare = ritenutaEcoWelfare * 100; %]
[!--
1. [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoAmministrazione %][/FORMAT]%<br/>
2. [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoFondo %][/FORMAT]%<br/>
3. [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoWelfare %][/FORMAT]%<br/>
4. [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]%<br/>
--]
<html> <html>
<head> <head>
<style> <style>
@@ -78,7 +71,7 @@ runtime:
<body> <body>
<!-- Header con logo UniPR come nel template standard --> <!-- Header con logo UniPR come nel template standard -->
<h2>IL DIRIGENTE</h2> <h2>IL DIRETTORE GENERALE</h2>
<p>visti lo Statuto dell'Universit&agrave; degli Studi di Parma ed il Regolamento Generale di Ateneo;</p> <p>visti lo Statuto dell'Universit&agrave; degli Studi di Parma ed il Regolamento Generale di Ateneo;</p>
@@ -90,7 +83,9 @@ runtime:
<!-- <p>preso atto che, con nota assunta a Prot. n. ___, il [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] ha trasmesso:</p> --> <!-- <p>preso atto che, con nota assunta a Prot. n. ___, il [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] ha trasmesso:</p> -->
<p>richiamato integralmente il testo del contratto da stipularsi tra l'Universit&agrave; degli Studi di Parma, nell'interesse del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG], avente ad oggetto [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] sotto la responsabilit&agrave; scientifica di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG], con durata di mesi [TAG]SCHEMAID,341,COL0008,IUQOID, , [/TAG], per un corrispettivo pari a euro [TAG]SCHEMAID,341,COL0094,IUQOID, , [/TAG];</p> <p>richiamato integralmente il testo del contratto da stipularsi tra l'Universit&agrave; degli Studi di Parma, nell'interesse del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] e [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG], avente ad oggetto [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] sotto la responsabilit&agrave; scientifica di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG], con durata di mesi [TAG]SCHEMAID,341,COL0008,IUQOID, , [/TAG], per un corrispettivo pari a euro [TAG]SCHEMAID,341,COL0094,IUQOID, , [/TAG];</p>
<!-- Indicazione domanda elixForms: "vista la domanda n.° <ID_DOMANDA>, ricevuta n.° <ID_RICEVUTA> (pervenuta il <DATA_INOLTRO> tramite il portale "Procedure Online");" -->
<p>ritenuto, per quanto premesso, di aderire alla richiesta di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG] di approvazione della stipula del contratto con [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] per [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] in premessa, ai sensi e per gli effetti di quanto previsto dal sopra citato Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza, didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi con riferimento all'Art.2, punto A;</p> <p>ritenuto, per quanto premesso, di aderire alla richiesta di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG] di approvazione della stipula del contratto con [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] per [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] in premessa, ai sensi e per gli effetti di quanto previsto dal sopra citato Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza, didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi con riferimento all'Art.2, punto A;</p>
@@ -99,7 +94,7 @@ runtime:
<ol> <ol>
<li>di approvare la stipula del contratto tra [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] e l'Universit&agrave; degli Studi di Parma, nell'interesse del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG], avente ad oggetto [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] sotto la responsabilit&agrave; scientifica di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG], con durata di mesi [TAG]SCHEMAID,341,COL0008,IUQOID, , [/TAG];</li> <li>di approvare la stipula del contratto tra [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] e l'Universit&agrave; degli Studi di Parma, nell'interesse del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG], avente ad oggetto [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] sotto la responsabilit&agrave; scientifica di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG], con durata di mesi [TAG]SCHEMAID,341,COL0008,IUQOID, , [/TAG];</li>
<li>di autorizzare l'introito del corrispettivo pari ad euro [TAG]SCHEMAID,341,COL0094,IUQOID, , [/TAG] che verr&agrave; erogato da [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0090,IUQOID, , [/TAG] != "N" %]--][% mostraRitenute != "N" %][/CONDITION][THEN], da assoggettare alle ritenute di cui all'art. 6, comma 1 del "Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza e didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi" nella misura del [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoAmministrazione %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0014,IUQOID, , [/TAG]) per l'Amministrazione di Ateneo, del [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoFondo %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0015,IUQOID, , [/TAG]) per il Fondo Comune di Ateneo e del [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoWelfare %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0016,IUQOID, , [/TAG]) per l'incremento dei fondi di cui agli artt. 119, comma 2, punto a) e 121, comma 2, punto a) del CCNL di comparto per l'attuazione dell'art. 110, comma 2 del medesimo contratto[IF][CONDITION][!--[% [TAG]SCHEMAID,337,COL0017,IUQOID, , [/TAG] != "" && [TAG]SCHEMAID,337,COL0017,IUQOID, , [/TAG] > 0 %]--][% ulterioreRitenuta2Max > 0 %][/CONDITION][THEN] e del [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0063,IUQOID, , [/TAG]) a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][/THEN][/IF][/THEN][/IF];</li> <li>di autorizzare l'introito del corrispettivo pari ad euro [TAG]SCHEMAID,341,COL0094,IUQOID, , [/TAG] che verr&agrave; erogato da [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0090,IUQOID, , [/TAG] != "N" %]--][% mostraRitenute != "N" %][/CONDITION][THEN], da assoggettare alle ritenute secondo le modalità previste dall'art. 6, comma 1 del "Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza e didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi" nella misura del [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoAmministrazione %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0014,IUQOID, , [/TAG]) per l'Amministrazione di Ateneo, del [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoFondo %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0015,IUQOID, , [/TAG]) per il Fondo Comune di Ateneo e del [FORMAT type="number" pattern="#,##0.##"][% percentualeEcoWelfare %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0016,IUQOID, , [/TAG]) per l'incremento dei fondi di cui agli artt. 119, comma 2, punto a) e 121, comma 2, punto a) del CCNL di comparto per l'attuazione dell'art. 110, comma 2 del medesimo contratto[IF][CONDITION][!--[% [TAG]SCHEMAID,337,COL0017,IUQOID, , [/TAG] != "" && [TAG]SCHEMAID,337,COL0017,IUQOID, , [/TAG] > 0 %]--][% ulterioreRitenuta2Max > 0 %][/CONDITION][THEN] e del [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0063,IUQOID, , [/TAG]) a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][/THEN][/IF][/THEN][/IF];</li>
<li>di dare mandato al Direttore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] per ogni adempimento relativo.</li> <li>di dare mandato al Direttore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] per ogni adempimento relativo.</li>
</ol> </ol>
@@ -45,13 +45,6 @@ runtime:
[% percentualeNonEcoFondo = ritenutaNonEcoFondo * 100; %] [% percentualeNonEcoFondo = ritenutaNonEcoFondo * 100; %]
[% percentualeNonEcoWelfare = ritenutaNonEcoWelfare * 100; %] [% percentualeNonEcoWelfare = ritenutaNonEcoWelfare * 100; %]
[!--
1. [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoAmministrazione %][/FORMAT]%<br/>
2. [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoFondo %][/FORMAT]%<br/>
3. [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoWelfare %][/FORMAT]%<br/>
4. [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]%<br/>
--]
<html> <html>
<head> <head>
<style> <style>
@@ -79,7 +72,7 @@ runtime:
<body> <body>
<!-- Header con logo UniPR come nel template standard --> <!-- Header con logo UniPR come nel template standard -->
<h2>IL DIRIGENTE</h2> <h2>IL DIRETTORE GENERALE</h2>
<p>visto l'art.15 della legge 7 agosto 1990 n. 241 che disciplina gli "Accordi tra Pubbliche Amministrazioni";</p> <p>visto l'art.15 della legge 7 agosto 1990 n. 241 che disciplina gli "Accordi tra Pubbliche Amministrazioni";</p>
@@ -101,7 +94,9 @@ runtime:
<p>verificata l'applicabilit&agrave; dell'art. 15 "Accordi fra Pubbliche Amministrazioni" della legge n. 241/1990 sul procedimento amministrativo, sussistendone i presupposti, incluso l'interesse reciproco, il contributo di tutti i soggetti sottoscrittori, la propriet&agrave; condivisa dei risultati secondo quanto stabilito dall'Accordo e la compartecipazione alle spese finalizzate al raggiungimento degli obiettivi specificati nel testo della stessa;</p> <p>verificata l'applicabilit&agrave; dell'art. 15 "Accordi fra Pubbliche Amministrazioni" della legge n. 241/1990 sul procedimento amministrativo, sussistendone i presupposti, incluso l'interesse reciproco, il contributo di tutti i soggetti sottoscrittori, la propriet&agrave; condivisa dei risultati secondo quanto stabilito dall'Accordo e la compartecipazione alle spese finalizzate al raggiungimento degli obiettivi specificati nel testo della stessa;</p>
<p>richiamato integralmente il testo dell'accordo da stipularsi tra l'Universit&agrave; degli Studi di Parma, nell'interesse del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG], avente ad oggetto [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] sotto la responsabilit&agrave; scientifica di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG], con durata di mesi [TAG]SCHEMAID,341,COL0008,IUQOID, , [/TAG][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0084,IUQOID, , [/TAG] == false %]--][% presenzaOneri == false %][/CONDITION][THEN], senza oneri a carico del budget dell'Amministrazione Centrale[/THEN][/IF];</p> <p>richiamato integralmente il testo dell'accordo da stipularsi tra l'Universit&agrave; degli Studi di Parma, nell'interesse del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] e [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG], avente ad oggetto [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] sotto la responsabilit&agrave; scientifica di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG], con durata di mesi [TAG]SCHEMAID,341,COL0008,IUQOID, , [/TAG][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0084,IUQOID, , [/TAG] == false %]--][% presenzaOneri == false %][/CONDITION][THEN], senza oneri a carico del budget dell'Amministrazione Centrale[/THEN][/IF];</p>
<!-- Indicazione domanda elixForms: "vista la domanda n.° <ID_DOMANDA>, ricevuta n.° <ID_RICEVUTA> (pervenuta il <DATA_INOLTRO> tramite il portale "Procedure Online");" -->
<p>ritenuto, per quanto premesso, di aderire alla richiesta di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG] di approvazione della stipula Accordo con [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] per [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] in premessa, ai sensi e per gli effetti di quanto previsto dal sopra citato Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza, didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi con riferimento all'Art.2, punto B;</p> <p>ritenuto, per quanto premesso, di aderire alla richiesta di [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG] di approvazione della stipula Accordo con [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] per [TAG]SCHEMAID,341,COL0005,IUQOID, , [/TAG] in premessa, ai sensi e per gli effetti di quanto previsto dal sopra citato Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza, didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi con riferimento all'Art.2, punto B;</p>
@@ -114,7 +109,7 @@ runtime:
<li>di autorizzare l'introito del contributo di euro [TAG]SCHEMAID,341,COL0094,IUQOID, , [/TAG] da parte di [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0090,IUQOID, , [/TAG] != "N" %]--][% mostraRitenute != "N" %][/CONDITION][THEN][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0051,IUQOID, , [/TAG] > 0 %]--][% speseGenerali > 0 %][/CONDITION][THEN], da assoggettare alle ritenute secondo le modalità previste dall'art. 6, comma 2 del "Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza e didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi" nella misura del [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoAmministrazione %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0049,IUQOID, , [/TAG]) per l'Amministrazione di Ateneo, del [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoFondo %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0050,IUQOID, , [/TAG]) per il Fondo Comune di Ateneo e del [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoWelfare %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0051,IUQOID, , [/TAG]) per l'incremento dei fondi di cui agli artt. 119, comma 2, punto a) e 121, comma 2, punto a) del CCNL di comparto per l'attuazione dell'art. 110, comma 2 del medesimo contratto[/THEN][/IF][IF][CONDITION][!--[% [TAG]SCHEMAID,337,COL0064,IUQOID, , [/TAG] != "" && [TAG]SCHEMAID,337,COL0064,IUQOID, , [/TAG] > 0 %]--][% ulterioreRitenuta2Max > 0 %][/CONDITION][THEN], con una ritenuta ulteriore del [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0068,IUQOID, , [/TAG]) a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][/THEN][/IF][/THEN][/IF];</li> <li>di autorizzare l'introito del contributo di euro [TAG]SCHEMAID,341,COL0094,IUQOID, , [/TAG] da parte di [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0090,IUQOID, , [/TAG] != "N" %]--][% mostraRitenute != "N" %][/CONDITION][THEN][IF][CONDITION][!--[% [TAG]SCHEMAID,341,COL0051,IUQOID, , [/TAG] > 0 %]--][% speseGenerali > 0 %][/CONDITION][THEN], da assoggettare alle ritenute secondo le modalità previste dall'art. 6, comma 2 del "Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza e didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi" nella misura del [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoAmministrazione %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0049,IUQOID, , [/TAG]) per l'Amministrazione di Ateneo, del [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoFondo %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0050,IUQOID, , [/TAG]) per il Fondo Comune di Ateneo e del [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoWelfare %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0051,IUQOID, , [/TAG]) per l'incremento dei fondi di cui agli artt. 119, comma 2, punto a) e 121, comma 2, punto a) del CCNL di comparto per l'attuazione dell'art. 110, comma 2 del medesimo contratto[/THEN][/IF][IF][CONDITION][!--[% [TAG]SCHEMAID,337,COL0064,IUQOID, , [/TAG] != "" && [TAG]SCHEMAID,337,COL0064,IUQOID, , [/TAG] > 0 %]--][% ulterioreRitenuta2Max > 0 %][/CONDITION][THEN], con una ritenuta ulteriore del [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]% (euro [TAG]SCHEMAID,337,COL0068,IUQOID, , [/TAG]) a favore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG][/THEN][/IF][/THEN][/IF];</li>
[/THEN][/IF] [/THEN][/IF]
<li>di conferire mandato al Direttore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] per l'adempimento di ogni attivit&agrave; relativa.</li> <li>di dare mandato al Direttore del [TAG]SCHEMAID,341,COL0006,IUQOID, , [/TAG] per ogni adempimento relativo.</li>
</ol> </ol>
<div class="firma"> <div class="firma">
@@ -45,13 +45,6 @@ runtime:
[% percentualeNonEcoFondo = ritenutaNonEcoFondo * 100; %] [% percentualeNonEcoFondo = ritenutaNonEcoFondo * 100; %]
[% percentualeNonEcoWelfare = ritenutaNonEcoWelfare * 100; %] [% percentualeNonEcoWelfare = ritenutaNonEcoWelfare * 100; %]
[!--
1. [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoAmministrazione %][/FORMAT]%<br/>
2. [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoFondo %][/FORMAT]%<br/>
3. [FORMAT type="number" pattern="#,##0.##"][% percentualeNonEcoWelfare %][/FORMAT]%<br/>
4. [FORMAT type="number" pattern="#,##0.##"][% ulterioreRitenuta2Max %][/FORMAT]%<br/>
--]
<html> <html>
<head> <head>
<style> <style>
@@ -79,7 +72,7 @@ runtime:
<body> <body>
<!-- Header con logo UniPR come nel template standard --> <!-- Header con logo UniPR come nel template standard -->
<h2>IL DIRIGENTE</h2> <h2>IL DIRETTORE GENERALE</h2>
<p>visto il Decreto Ministeriale 30 novembre 2021 recante "Misure volte a facilitare e sostenere la realizzazione degli studi clinici di medicinali senza scopo di lucro e degli studi osservazionali e a disciplinare la cessione di dati e risultati di sperimentazioni senza scopo di lucro a fini registrativi, ai sensi dell'art. 1, comma 1, lettera c), del decreto legislativo 14 maggio 2019, n. 52";</p> <p>visto il Decreto Ministeriale 30 novembre 2021 recante "Misure volte a facilitare e sostenere la realizzazione degli studi clinici di medicinali senza scopo di lucro e degli studi osservazionali e a disciplinare la cessione di dati e risultati di sperimentazioni senza scopo di lucro a fini registrativi, ai sensi dell'art. 1, comma 1, lettera c), del decreto legislativo 14 maggio 2019, n. 52";</p>
@@ -99,6 +92,8 @@ runtime:
<p>preso atto dell'autorizzazione all'avvio dello studio rilasciata in data ___ da ___;</p> <p>preso atto dell'autorizzazione all'avvio dello studio rilasciata in data ___ da ___;</p>
<!-- Indicazione domanda elixForms: "vista la domanda n.° <ID_DOMANDA>, ricevuta n.° <ID_RICEVUTA> (pervenuta il <DATA_INOLTRO> tramite il portale "Procedure Online");" -->
<p>ritenuto, per quanto premesso, di aderire alla richiesta avanzata da [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG] di approvazione della stipula del contratto con [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] per la conduzione della sperimentazione sopra descritta, ai sensi e per gli effetti di quanto previsto dal sopra citato Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza, didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi con riferimento all'Art.2, lettera B;</p> <p>ritenuto, per quanto premesso, di aderire alla richiesta avanzata da [TAG]SCHEMAID,341,COL0049,IUQOID, , [/TAG] di approvazione della stipula del contratto con [TAG]SCHEMAID,341,COL0086,IUQOID, , [/TAG] per la conduzione della sperimentazione sopra descritta, ai sensi e per gli effetti di quanto previsto dal sopra citato Regolamento sulla disciplina delle attivit&agrave; di ricerca, consulenza, didattica e alta formazione eseguite dall'Universit&agrave; degli Studi di Parma a fronte di contratti o accordi con soggetti terzi con riferimento all'Art.2, lettera B;</p>
<h2>determina</h2> <h2>determina</h2>
+9 -5
View File
@@ -1,17 +1,21 @@
function Import-PowerShellYamlModule { function Initialize-PowerShellEnvironment {
Write-Host "Initializing PowerShell environment..." -ForegroundColor Yellow
# Add any environment setup logic here, such as importing modules, setting variables, etc.
# Example: Import-Module SomeModule
Import-Module powershell-yaml -ErrorAction SilentlyContinue Import-Module powershell-yaml -ErrorAction SilentlyContinue
Write-Host "PowerShell environment initialized." -ForegroundColor Green
} }
function Invoke-Main { function Invoke-Main {
Write-Host "Preparing environment..." -ForegroundColor Cyan Write-Host "Preparing environment..." -ForegroundColor Cyan
Write-Host Write-Host
Write-Host "Initializing PowerShell environment..." -ForegroundColor Yellow Initialize-PowerShellEnvironment
Import-PowerShellYamlModule
Write-Host "PowerShell environment initialized." -ForegroundColor Green
Write-Host Write-Host
Write-Host "Environment preparation complete!" -ForegroundColor Green Write-Host "Environment preparation complete!" -ForegroundColor Green
} }
Invoke-Main Invoke-Main
-48
View File
@@ -1,48 +0,0 @@
$setupToolsScript = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot '..\scripts\setup-tools.ps1')).Path
$expectedOutput = @(
'Preparing environment...'
''
'Initializing PowerShell environment...'
'PowerShell environment initialized.'
''
'Environment preparation complete!'
) -join "`n"
Describe 'setup-tools.ps1' {
It 'imports powershell-yaml and preserves the user-facing output' {
$originalModulePath = $env:PSModulePath
try {
$moduleRoot = Join-Path $TestDrive 'available-modules'
$moduleDirectory = Join-Path $moduleRoot 'powershell-yaml'
$null = New-Item -ItemType Directory -Path $moduleDirectory
Set-Content -LiteralPath (Join-Path $moduleDirectory 'powershell-yaml.psm1') -Value ''
$env:PSModulePath = $moduleRoot
$escapedScriptPath = $setupToolsScript.Replace("'", "''")
$command = "& '$escapedScriptPath'; if (-not (Get-Module -Name powershell-yaml)) { exit 42 }"
$output = @(& pwsh -NoProfile -Command $command 6>&1 | ForEach-Object { $_.ToString() })
$LASTEXITCODE | Should Be 0
($output -join "`n") | Should Be $expectedOutput
}
finally {
$env:PSModulePath = $originalModulePath
}
}
It 'continues successfully when powershell-yaml is unavailable' {
$originalModulePath = $env:PSModulePath
try {
$env:PSModulePath = Join-Path $TestDrive 'missing-modules'
$output = @(& pwsh -NoProfile -File $setupToolsScript 6>&1 | ForEach-Object { $_.ToString() })
$LASTEXITCODE | Should Be 0
($output -join "`n") | Should Be $expectedOutput
}
finally {
$env:PSModulePath = $originalModulePath
}
}
}